mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-22 05:26:17 +02:00
basic coreAudio playback is working
This commit is contained in:
parent
71e0a89e29
commit
20ab3deedb
4 changed files with 81 additions and 10 deletions
|
@ -119,7 +119,7 @@ void Controller::onMessageReceived(ClientConnection* connection, const msg::Base
|
|||
#elif HAS_COREAUDIO
|
||||
player_.reset(new CoreAudioPlayer(pcmDevice_, stream_.get()));
|
||||
#else
|
||||
throw SnapException("No ALSA or OPENSL support");
|
||||
throw SnapException("No audio player support");
|
||||
#endif
|
||||
player_->setVolume(serverSettings_->getVolume() / 100.);
|
||||
player_->setMute(serverSettings_->isMuted());
|
||||
|
|
|
@ -18,9 +18,7 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <AudioToolbox/AudioQueue.h>
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#include <CoreFoundation/CFRunLoop.h>
|
||||
|
||||
|
||||
#include "coreAudioPlayer.h"
|
||||
|
||||
|
@ -28,8 +26,17 @@
|
|||
//http://stackoverflow.com/questions/4863811/how-to-use-audioqueue-to-play-a-sound-for-mac-osx-in-c
|
||||
//https://gist.github.com/andormade/1360885
|
||||
|
||||
void callback(void *custom_data, AudioQueueRef queue, AudioQueueBufferRef buffer)
|
||||
{
|
||||
CoreAudioPlayer* player = static_cast<CoreAudioPlayer*>(custom_data);
|
||||
player->playerCallback(queue, buffer);
|
||||
}
|
||||
|
||||
CoreAudioPlayer::CoreAudioPlayer(const PcmDevice& pcmDevice, Stream* stream) : Player(pcmDevice, stream)
|
||||
|
||||
CoreAudioPlayer::CoreAudioPlayer(const PcmDevice& pcmDevice, Stream* stream) :
|
||||
Player(pcmDevice, stream),
|
||||
ms_(50),
|
||||
pubStream_(stream)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,12 +46,67 @@ CoreAudioPlayer::~CoreAudioPlayer()
|
|||
}
|
||||
|
||||
|
||||
void CoreAudioPlayer::worker()
|
||||
void CoreAudioPlayer::playerCallback(AudioQueueRef queue, AudioQueueBufferRef bufferRef)
|
||||
{
|
||||
while (active_)
|
||||
//logO << "Callback\n";
|
||||
chronos::usec delay(ms_ * 1000);
|
||||
char *buffer = (char*)bufferRef->mAudioData;
|
||||
if (!pubStream_->getPlayerChunk(buffer, delay, frames_))
|
||||
{
|
||||
usleep(100*1000);
|
||||
logO << "Failed to get chunk. Playing silence.\n";
|
||||
memset(buffer, 0, buff_size_);
|
||||
}
|
||||
else
|
||||
{
|
||||
adjustVolume(buffer, frames_);
|
||||
}
|
||||
|
||||
// OSStatus status =
|
||||
AudioQueueEnqueueBuffer(queue, bufferRef, 0, NULL);
|
||||
|
||||
if (!active_)
|
||||
{
|
||||
AudioQueueStop(queue, false);
|
||||
AudioQueueDispose(queue, false);
|
||||
CFRunLoopStop(CFRunLoopGetCurrent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CoreAudioPlayer::worker()
|
||||
{
|
||||
AudioStreamBasicDescription format;
|
||||
AudioQueueRef queue;
|
||||
AudioQueueBufferRef buffers[2];
|
||||
|
||||
const SampleFormat& sampleFormat = pubStream_->getFormat();
|
||||
|
||||
format.mSampleRate = sampleFormat.rate;
|
||||
format.mFormatID = kAudioFormatLinearPCM;
|
||||
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;// | kAudioFormatFlagIsPacked;
|
||||
format.mBitsPerChannel = sampleFormat.bits;
|
||||
format.mChannelsPerFrame = sampleFormat.channels;
|
||||
format.mBytesPerFrame = sampleFormat.frameSize;
|
||||
format.mFramesPerPacket = 1;
|
||||
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
|
||||
format.mReserved = 0;
|
||||
|
||||
AudioQueueNewOutput(&format, callback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &queue);
|
||||
|
||||
frames_ = (sampleFormat.rate * ms_) / 1000;
|
||||
ms_ = frames_ * 1000 / sampleFormat.rate;
|
||||
logO << "frames: " << frames_ << ", ms: " << ms_ << "\n";
|
||||
buff_size_ = frames_ * sampleFormat.frameSize;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
AudioQueueAllocateBuffer(queue, buff_size_, &buffers[i]);
|
||||
buffers[i]->mAudioDataByteSize = buff_size_;
|
||||
callback(this, queue, buffers[i]);
|
||||
}
|
||||
|
||||
logE << "CoreAudioPlayer::worker\n";
|
||||
AudioQueueStart(queue, NULL);
|
||||
CFRunLoopRun();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
#ifndef CORE_AUDIO_PLAYER_H
|
||||
#define CORE_AUDIO_PLAYER_H
|
||||
|
||||
#include "player.h"
|
||||
#include <AudioToolbox/AudioQueue.h>
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#include <CoreFoundation/CFRunLoop.h>
|
||||
|
||||
#include "player.h"
|
||||
|
||||
/// Audio Player
|
||||
/**
|
||||
|
@ -32,9 +35,15 @@ public:
|
|||
CoreAudioPlayer(const PcmDevice& pcmDevice, Stream* stream);
|
||||
virtual ~CoreAudioPlayer();
|
||||
|
||||
void playerCallback(AudioQueueRef queue, AudioQueueBufferRef bufferRef);
|
||||
|
||||
protected:
|
||||
virtual void worker();
|
||||
|
||||
size_t ms_;
|
||||
size_t frames_;
|
||||
size_t buff_size_;
|
||||
Stream* pubStream_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
namespace chronos
|
||||
{
|
||||
typedef std::chrono::high_resolution_clock hrc;
|
||||
typedef std::chrono::system_clock hrc;
|
||||
typedef std::chrono::time_point<hrc> time_point_hrc;
|
||||
typedef std::chrono::seconds sec;
|
||||
typedef std::chrono::milliseconds msec;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue