- Only use mpg123decoder in *nix -- the Tuniac one doesn't work out of the box

- Added CMake support for oggdecoder
- Fleshed out most of the CoreAudioOut implementation -- but it's playing at 2x speed (some sort of buffering issue)
This commit is contained in:
Casey Langen 2016-05-27 00:22:26 -07:00
parent e172c258e4
commit 7ed083a692
7 changed files with 219 additions and 56 deletions

View File

@ -24,8 +24,8 @@ add_definitions (-DHAVE_BOOST
set (BOOST_LINK_LIBS set (BOOST_LINK_LIBS
${Boost_LIBRARIES}) ${Boost_LIBRARIES})
#message(STATUS "Libs: " ${BOOST_LINK_LIBS}) #message(STATUS "boost libs: " ${BOOST_LINK_LIBS})
#message(STATUS "Includes: " ${Boost_INCLUDE_DIRS}) #message(STATUS "boost includes: " ${Boost_INCLUDE_DIRS})
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Modules) ${CMAKE_CURRENT_SOURCE_DIR}/Modules)
@ -55,6 +55,6 @@ add_subdirectory(src/3rdparty)
add_subdirectory(src/core) add_subdirectory(src/core)
add_subdirectory(src/musikbox) add_subdirectory(src/musikbox)
add_subdirectory(src/contrib/taglib_plugin) add_subdirectory(src/contrib/taglib_plugin)
add_subdirectory(src/contrib/mp3decoder) add_subdirectory(src/contrib/oggdecoder)
add_subdirectory(src/contrib/mpg123decoder) add_subdirectory(src/contrib/mpg123decoder)
add_subdirectory(src/contrib/coreaudioout) add_subdirectory(src/contrib/coreaudioout)

View File

@ -3,9 +3,15 @@ set (coreaudioout_SOURCES
CoreAudioOut.cpp CoreAudioOut.cpp
) )
add_definitions( IF(APPLE)
-D_DEBUG FIND_LIBRARY(CORE_FOUNDATION_LIBRARY CoreFoundation)
) FIND_LIBRARY(CORE_AUDIO_LIBRARY CoreAudio)
FIND_LIBRARY(AUDIO_TOOLBOX_LIBRARY AudioToolbox)
MARK_AS_ADVANCED (CORE_FOUNDATION_LIBRARY
CORE_AUDIO_LIBRARY
AUDIO_TOOLBOX_LIBRARY)
SET(FRAMEWORK_LIBS ${CORE_FOUNDATION_LIBRARY} ${CORE_AUDIO_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY})
ENDIF (APPLE)
add_library(coreaudioout SHARED ${coreaudioout_SOURCES}) add_library(coreaudioout SHARED ${coreaudioout_SOURCES})
target_link_libraries(coreaudioout ${musikbox_LINK_LIBS}) target_link_libraries(coreaudioout ${musikbox_LINK_LIBS} ${FRAMEWORK_LIBS})

View File

@ -1,35 +1,183 @@
#include "CoreAudioOut.h" #include "CoreAudioOut.h"
#include <iostream>
#define BUFFER_COUNT 3
using namespace musik::core::audio; using namespace musik::core::audio;
void audioCallback(void *customData, AudioQueueRef queue, AudioQueueBufferRef buffer)
{
OSStatus result = AudioQueueFreeBuffer(queue, buffer);
if (result != 0) {
std::cerr << "AudioQueueFreeBuffer failed: " << result << "\n";
}
CoreAudioOut* output = (CoreAudioOut *) customData;
IBuffer* coreBuffer = (IBuffer *) buffer->mUserData;
output->NotifyBufferCompleted(coreBuffer);
}
void CoreAudioOut::NotifyBufferCompleted(IBuffer *buffer) {
boost::recursive_mutex::scoped_lock lock(this->mutex);
--bufferCount;
this->bufferProvider->OnBufferProcessed(buffer);
}
CoreAudioOut::CoreAudioOut() { CoreAudioOut::CoreAudioOut() {
this->bufferProvider = NULL;
this->quit = false;
this->bufferCount = 0;
} this->audioFormat = (AudioStreamBasicDescription) { 0 };
CoreAudioOut::~CoreAudioOut() { this->audioFormat.mFormatID = kAudioFormatLinearPCM;
this->audioFormat.mFormatFlags = kAudioFormatFlagIsFloat;
this->audioFormat.mFramesPerPacket = 1;
this->audioFormat.mBitsPerChannel = 32;
this->audioFormat.mReserved = 0;
} /* these get filled in later */
this->audioFormat.mChannelsPerFrame = -1;
void CoreAudioOut::Destroy() { this->audioFormat.mSampleRate = -1;
this->audioFormat.mBytesPerFrame = -1;
} this->audioFormat.mBytesPerPacket = -1;
void CoreAudioOut::Pause() {
}
void CoreAudioOut::Resume() {
}
void CoreAudioOut::SetVolume(double volume) {
}
void CoreAudioOut::Stop() {
this->audioQueue = NULL;
} }
bool CoreAudioOut::Play(IBuffer *buffer, IBufferProvider *provider) { bool CoreAudioOut::Play(IBuffer *buffer, IBufferProvider *provider) {
boost::recursive_mutex::scoped_lock lock(this->mutex);
if (this->bufferCount >= BUFFER_COUNT) {
/* enough buffers are already in the queue. bail, we'll notify the
caller when there's more data available */
return false; return false;
}
OSStatus result;
if (buffer->SampleRate() != this->audioFormat.mSampleRate ||
buffer->Channels() != this->audioFormat.mChannelsPerFrame ||
this->audioQueue == NULL)
{
this->audioFormat.mSampleRate = buffer->SampleRate();
this->audioFormat.mChannelsPerFrame = buffer->Channels();
this->audioFormat.mBytesPerFrame = (this->audioFormat.mBitsPerChannel / 8) * this->audioFormat.mChannelsPerFrame;
this->audioFormat.mBytesPerPacket = this->audioFormat.mBytesPerFrame * this->audioFormat.mFramesPerPacket;
this->Stop();
result = AudioQueueNewOutput(
&this->audioFormat,
audioCallback,
this,
NULL,
kCFRunLoopCommonModes,
0,
&this->audioQueue);
if (result != 0) {
std::cerr << "AudioQueueNewOutput failed: " << result << "\n";
return false;
}
result = AudioQueueStart(this->audioQueue, NULL);
if (result != 0) {
std::cerr << "AudioQueueStart failed: " << result << "\n";
return false;
}
}
this->bufferProvider = provider;
AudioQueueBufferRef audioQueueBuffer = NULL;
result = AudioQueueAllocateBuffer(
this->audioQueue, buffer->Bytes(), &audioQueueBuffer);
if (result != 0) {
std::cerr << "AudioQueueAllocateBuffer failed: " << result << "\n";
return false;
}
audioQueueBuffer->mUserData = (void *) buffer;
audioQueueBuffer->mAudioDataByteSize = buffer->Bytes();
memcpy(
audioQueueBuffer->mAudioData,
(void *) buffer->BufferPointer(),
buffer->Bytes());
result = AudioQueueEnqueueBuffer(
this->audioQueue, audioQueueBuffer, 0, NULL);
if (result != 0) {
std::cerr << "AudioQueueEnqueueBuffer failed: " << result << "\n";
return false;
}
++bufferCount;
return true;
}
CoreAudioOut::~CoreAudioOut() {
this->Stop();
}
void CoreAudioOut::Destroy() {
delete this;
}
void CoreAudioOut::Pause() {
boost::recursive_mutex::scoped_lock lock(this->mutex);
if (this->audioQueue) {
AudioQueuePause(this->audioQueue);
}
}
void CoreAudioOut::Resume() {
boost::recursive_mutex::scoped_lock lock(this->mutex);
if (this->audioQueue) {
AudioQueueStart(this->audioQueue, NULL);
}
}
void CoreAudioOut::SetVolume(double volume) {
boost::recursive_mutex::scoped_lock lock(this->mutex);
if (this->audioQueue) {
OSStatus result = AudioQueueSetParameter(
this->audioQueue,
kAudioQueueParam_Volume,
volume);
if (result != 0) {
std::cerr << "AudioQueueSetParameter(volume) failed: " << result << "\n";
}
}
}
void CoreAudioOut::Stop() {
AudioQueueRef queue = NULL;
{
/* AudioQueueStop/AudioQueueDispose will trigger the callback, which
will try to dispose of the samples on a separate thread and deadlock.
cache the queue and reset outside of the critical section */
boost::recursive_mutex::scoped_lock lock(this->mutex);
queue = this->audioQueue;
this->audioQueue = NULL;
}
if (queue) {
AudioQueueStop(queue, true);
AudioQueueDispose(queue, true);
}
} }

View File

@ -2,6 +2,13 @@
#include <core/sdk/IOutput.h> #include <core/sdk/IOutput.h>
#include <core/sdk/IBufferProvider.h> #include <core/sdk/IBufferProvider.h>
#include <queue>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <AudioToolbox/AudioQueue.h>
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CFRunLoop.h>
class CoreAudioOut : public musik::core::audio::IOutput { class CoreAudioOut : public musik::core::audio::IOutput {
public: public:
@ -17,4 +24,15 @@ class CoreAudioOut : public musik::core::audio::IOutput {
virtual bool Play( virtual bool Play(
musik::core::audio::IBuffer *buffer, musik::core::audio::IBuffer *buffer,
musik::core::audio::IBufferProvider *provider); musik::core::audio::IBufferProvider *provider);
void NotifyBufferCompleted(musik::core::audio::IBuffer *buffer);
private:
musik::core::audio::IBufferProvider *bufferProvider;
AudioStreamBasicDescription audioFormat;
AudioQueueRef audioQueue;
size_t bufferCount;
boost::thread thread;
boost::recursive_mutex mutex;
bool quit;
}; };

View File

@ -1,26 +1,9 @@
set ( oggdecoder_SOURCES set (oggdecoder_SOURCES
oggdecoder_plugin.cpp oggdecoder_plugin.cpp
OGGDecoder.cpp OggDecoder.cpp
OggSourceSupplier.cpp OggDecoderFactory.cpp
stdafx.cpp stdafx.cpp
)
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
add_definitions(-DWIN32)
if(NOT DEFINED MINGW)
endif(NOT DEFINED MINGW)
else(CMAKE_SYSTEM_NAME MATCHES "Windows")
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fpermissive)
endif(CMAKE_SYSTEM_NAME MATCHES "Windows")
add_definitions(
-DXML_STATIC
-D_CRT_SECURE_NO_DEPRECATE
-D_DEBUG
) )
add_library( oggdecoder SHARED ${oggdecoder_SOURCES} ) add_library(oggdecoder SHARED ${oggdecoder_SOURCES})
target_link_libraries( oggdecoder ${musikCube_LINK_LIBS}) target_link_libraries(oggdecoder ${musikbox_LINK_LIBS} ogg vorbis vorbisfile)

View File

@ -40,9 +40,17 @@
#include "OggDecoderFactory.h" #include "OggDecoderFactory.h"
#ifdef WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
#ifdef WIN32
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
return true; return true;
} }
#endif
class OggDecoderPlugin : public musik::core::IPlugin { class OggDecoderPlugin : public musik::core::IPlugin {
public: public:
@ -52,10 +60,10 @@ public:
const char* Author() { return "Björn Olievier, _avatar"; }; const char* Author() { return "Björn Olievier, _avatar"; };
}; };
extern "C" __declspec(dllexport) musik::core::IPlugin* GetPlugin() { extern "C" DLLEXPORT musik::core::IPlugin* GetPlugin() {
return new OggDecoderPlugin(); return new OggDecoderPlugin();
} }
extern "C" __declspec(dllexport) IDecoderFactory* GetDecoderFactory() { extern "C" DLLEXPORT IDecoderFactory* GetDecoderFactory() {
return new OggDecoderFactory(); return new OggDecoderFactory();
} }