AudioQueueServices fix

This commit is contained in:
Jack Andersen 2016-03-08 11:18:38 -10:00
parent 1b3209f4bf
commit 0dfab1fdad
5 changed files with 141 additions and 81 deletions

@ -1 +1 @@
Subproject commit cb9c7d7bd57c09fd73c5aadfc881c0140b64fcdb Subproject commit 9bfc3ae1c149bb8272af3809099fff78ce780cd8

View File

@ -37,7 +37,7 @@ struct AQSAudioVoice : IAudioVoice
IAudioVoiceCallback* m_cb; IAudioVoiceCallback* m_cb;
AudioQueueRef m_queue = nullptr; AudioQueueRef m_queue = nullptr;
AudioQueueBufferRef m_buffers[3]; AudioQueueBufferRef m_buffers[3];
size_t m_bufferFrames = 2048; size_t m_bufferFrames = 1024;
size_t m_frameSize; size_t m_frameSize;
const ChannelMap& channelMap() const {return m_map;} const ChannelMap& channelMap() const {return m_map;}
@ -48,7 +48,7 @@ struct AQSAudioVoice : IAudioVoice
{ {
AQSAudioVoice* voice = static_cast<AQSAudioVoice*>(inUserData); AQSAudioVoice* voice = static_cast<AQSAudioVoice*>(inUserData);
voice->m_callbackBuf = inBuffer; voice->m_callbackBuf = inBuffer;
voice->m_cb->needsNextBuffer(voice, voice->m_bufferFrames); voice->m_cb->needsNextBuffer(*voice, voice->m_bufferFrames);
voice->m_callbackBuf = nullptr; voice->m_callbackBuf = nullptr;
} }
@ -80,73 +80,81 @@ struct AQSAudioVoice : IAudioVoice
} }
if (err) if (err)
{ {
Log.report(logvisor::Error, "unable to create output audio queue"); Log.report(logvisor::Fatal, "unable to create output audio queue");
return; return;
} }
AudioChannelLayout layout; if (chCount > 2)
UInt32 layoutSz = sizeof(layout);
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz))
{ {
Log.report(logvisor::Error, "unable to get channel layout from audio queue"); AudioChannelLayout layout;
return; UInt32 layoutSz = sizeof(layout);
} if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz))
switch (layout.mChannelLayoutTag)
{
case kAudioChannelLayoutTag_UseChannelDescriptions:
m_map.m_channelCount = layout.mNumberChannelDescriptions;
for (int i=0 ; i<layout.mNumberChannelDescriptions ; ++i)
{ {
AudioChannel ch = AQSChannelToBooChannel(layout.mChannelDescriptions[i].mChannelLabel); Log.report(logvisor::Fatal, "unable to get channel layout from audio queue");
m_map.m_channels[i] = ch; return;
} }
break;
case kAudioChannelLayoutTag_UseChannelBitmap: switch (layout.mChannelLayoutTag)
if ((layout.mChannelBitmap & kAudioChannelBit_Left) != 0) {
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontLeft; case kAudioChannelLayoutTag_UseChannelDescriptions:
if ((layout.mChannelBitmap & kAudioChannelBit_Right) != 0) m_map.m_channelCount = layout.mNumberChannelDescriptions;
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontRight; for (int i=0 ; i<layout.mNumberChannelDescriptions ; ++i)
if ((layout.mChannelBitmap & kAudioChannelBit_Center) != 0) {
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontCenter; AudioChannel ch = AQSChannelToBooChannel(layout.mChannelDescriptions[i].mChannelLabel);
if ((layout.mChannelBitmap & kAudioChannelBit_LFEScreen) != 0) m_map.m_channels[i] = ch;
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::LFE; }
if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurround) != 0) break;
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearLeft; case kAudioChannelLayoutTag_UseChannelBitmap:
if ((layout.mChannelBitmap & kAudioChannelBit_RightSurround) != 0) if ((layout.mChannelBitmap & kAudioChannelBit_Left) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearRight; m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurroundDirect) != 0) if ((layout.mChannelBitmap & kAudioChannelBit_Right) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideLeft; m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontRight;
if ((layout.mChannelBitmap & kAudioChannelBit_RightSurroundDirect) != 0) if ((layout.mChannelBitmap & kAudioChannelBit_Center) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideRight; m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontCenter;
break; if ((layout.mChannelBitmap & kAudioChannelBit_LFEScreen) != 0)
case kAudioChannelLayoutTag_Stereo: m_map.m_channels[m_map.m_channelCount++] = AudioChannel::LFE;
case kAudioChannelLayoutTag_StereoHeadphones: if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurround) != 0)
m_map.m_channelCount = 2; m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearLeft;
m_map.m_channels[0] = AudioChannel::FrontLeft; if ((layout.mChannelBitmap & kAudioChannelBit_RightSurround) != 0)
m_map.m_channels[1] = AudioChannel::FrontRight; m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearRight;
break; if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurroundDirect) != 0)
case kAudioChannelLayoutTag_Quadraphonic: m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideLeft;
m_map.m_channelCount = 4; if ((layout.mChannelBitmap & kAudioChannelBit_RightSurroundDirect) != 0)
m_map.m_channels[0] = AudioChannel::FrontLeft; m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideRight;
m_map.m_channels[1] = AudioChannel::FrontRight; break;
m_map.m_channels[2] = AudioChannel::RearLeft; case kAudioChannelLayoutTag_Stereo:
m_map.m_channels[3] = AudioChannel::RearRight; case kAudioChannelLayoutTag_StereoHeadphones:
break; m_map.m_channelCount = 2;
case kAudioChannelLayoutTag_Pentagonal: m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channelCount = 5; m_map.m_channels[1] = AudioChannel::FrontRight;
m_map.m_channels[0] = AudioChannel::FrontLeft; break;
m_map.m_channels[1] = AudioChannel::FrontRight; case kAudioChannelLayoutTag_Quadraphonic:
m_map.m_channels[2] = AudioChannel::RearLeft; m_map.m_channelCount = 4;
m_map.m_channels[3] = AudioChannel::RearRight; m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channels[4] = AudioChannel::FrontCenter; m_map.m_channels[1] = AudioChannel::FrontRight;
break; m_map.m_channels[2] = AudioChannel::RearLeft;
default: m_map.m_channels[3] = AudioChannel::RearRight;
Log.report(logvisor::Error, "unknown channel layout %u; using stereo", layout.mChannelLayoutTag); break;
m_map.m_channelCount = 2; case kAudioChannelLayoutTag_Pentagonal:
m_map.m_channels[0] = AudioChannel::FrontLeft; m_map.m_channelCount = 5;
m_map.m_channels[1] = AudioChannel::FrontRight; m_map.m_channels[0] = AudioChannel::FrontLeft;
break; m_map.m_channels[1] = AudioChannel::FrontRight;
m_map.m_channels[2] = AudioChannel::RearLeft;
m_map.m_channels[3] = AudioChannel::RearRight;
m_map.m_channels[4] = AudioChannel::FrontCenter;
break;
default:
Log.report(logvisor::Fatal, "unknown channel layout %u; using stereo", layout.mChannelLayoutTag);
m_map.m_channelCount = 2;
m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channels[1] = AudioChannel::FrontRight;
break;
}
}
else
{
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontLeft;
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontRight;
} }
while (m_map.m_channelCount < chCount) while (m_map.m_channelCount < chCount)
@ -155,7 +163,7 @@ struct AQSAudioVoice : IAudioVoice
for (int i=0 ; i<3 ; ++i) for (int i=0 ; i<3 ; ++i)
if (AudioQueueAllocateBuffer(m_queue, m_bufferFrames * chCount * 2, &m_buffers[i])) if (AudioQueueAllocateBuffer(m_queue, m_bufferFrames * chCount * 2, &m_buffers[i]))
{ {
Log.report(logvisor::Error, "unable to create audio queue buffer"); Log.report(logvisor::Fatal, "unable to create audio queue buffer");
AudioQueueDispose(m_queue, false); AudioQueueDispose(m_queue, false);
m_queue = nullptr; m_queue = nullptr;
return; return;
@ -166,7 +174,7 @@ struct AQSAudioVoice : IAudioVoice
for (unsigned i=0 ; i<3 ; ++i) for (unsigned i=0 ; i<3 ; ++i)
{ {
m_primeBuf = i; m_primeBuf = i;
m_cb->needsNextBuffer(this, m_bufferFrames); m_cb->needsNextBuffer(*this, m_bufferFrames);
} }
AudioQueuePrime(m_queue, 0, nullptr); AudioQueuePrime(m_queue, 0, nullptr);
} }
@ -206,6 +214,56 @@ struct AQSAudioVoice : IAudioVoice
struct AQSAudioVoiceAllocator : IAudioVoiceAllocator struct AQSAudioVoiceAllocator : IAudioVoiceAllocator
{ {
static void DummyCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {}
AudioChannelSet getAvailableSet()
{
const unsigned chCount = 8;
AudioStreamBasicDescription desc = {};
desc.mSampleRate = 32000;
desc.mFormatID = kAudioFormatLinearPCM;
desc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
desc.mBytesPerPacket = chCount * 2;
desc.mFramesPerPacket = 1;
desc.mBytesPerFrame = chCount * 2;
desc.mChannelsPerFrame = chCount;
desc.mBitsPerChannel = 16;
AudioQueueRef queue;
if (AudioQueueNewOutput(&desc, AudioQueueOutputCallback(DummyCallback),
this, nullptr, nullptr, 0, &queue))
{
Log.report(logvisor::Error, "unable to create output audio queue");
return AudioChannelSet::Unknown;
}
UInt32 hwChannels;
UInt32 channelsSz = sizeof(UInt32);
if (AudioQueueGetProperty(queue, kAudioQueueDeviceProperty_NumberChannels, &hwChannels, &channelsSz))
{
Log.report(logvisor::Error, "unable to get channel count from audio queue");
AudioQueueDispose(queue, true);
return AudioChannelSet::Unknown;
}
AudioQueueDispose(queue, true);
switch (hwChannels)
{
case 2:
return AudioChannelSet::Stereo;
case 4:
return AudioChannelSet::Quad;
case 6:
return AudioChannelSet::Surround51;
case 8:
return AudioChannelSet::Surround71;
default: break;
}
return AudioChannelSet::Unknown;
}
std::unique_ptr<IAudioVoice> allocateNewVoice(AudioChannelSet layoutOut, std::unique_ptr<IAudioVoice> allocateNewVoice(AudioChannelSet layoutOut,
unsigned sampleRate, unsigned sampleRate,
IAudioVoiceCallback* cb) IAudioVoiceCallback* cb)
@ -216,6 +274,8 @@ struct AQSAudioVoiceAllocator : IAudioVoiceAllocator
return {}; return {};
return ret; return ret;
} }
void pumpVoices() {}
}; };
std::unique_ptr<IAudioVoiceAllocator> NewAudioVoiceAllocator() std::unique_ptr<IAudioVoiceAllocator> NewAudioVoiceAllocator()

View File

@ -1,6 +1,6 @@
#include "../mac/CocoaCommon.hpp" #include "../mac/CocoaCommon.hpp"
#if BOO_HAS_METAL #if BOO_HAS_METAL
#include <LogVisor/LogVisor.hpp> #include "logvisor/logvisor.hpp"
#include "boo/graphicsdev/Metal.hpp" #include "boo/graphicsdev/Metal.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include <vector> #include <vector>
@ -14,7 +14,7 @@
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::Metal"); static logvisor::Module Log("boo::Metal");
struct MetalCommandQueue; struct MetalCommandQueue;
ThreadLocalPtr<struct MetalData> MetalDataFactory::m_deferredData; ThreadLocalPtr<struct MetalData> MetalDataFactory::m_deferredData;
@ -198,7 +198,7 @@ class MetalTextureD : public ITextureD
m_pxPitch = 1; m_pxPitch = 1;
break; break;
default: default:
Log.report(LogVisor::FatalError, "unsupported tex format"); Log.report(logvisor::Fatal, "unsupported tex format");
} }
m_cpuSz = width * height * m_pxPitch; m_cpuSz = width * height * m_pxPitch;
@ -444,7 +444,7 @@ class MetalShaderPipeline : public IShaderPipeline
NSError* err = nullptr; NSError* err = nullptr;
m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err]; m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err];
if (err) if (err)
Log.report(LogVisor::FatalError, "error making shader pipeline: %s", Log.report(logvisor::Fatal, "error making shader pipeline: %s",
[[err localizedDescription] UTF8String]); [[err localizedDescription] UTF8String]);
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
@ -962,14 +962,14 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con
options:compOpts options:compOpts
error:&err]; error:&err];
if (err) if (err)
Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]); Log.report(logvisor::Fatal, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]);
id<MTLFunction> vertFunc = [vertShaderLib newFunctionWithName:@"vmain"]; id<MTLFunction> vertFunc = [vertShaderLib newFunctionWithName:@"vmain"];
id<MTLLibrary> fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource) id<MTLLibrary> fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource)
options:compOpts options:compOpts
error:&err]; error:&err];
if (err) if (err)
Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]); Log.report(logvisor::Fatal, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]);
id<MTLFunction> fragFunc = [fragShaderLib newFunctionWithName:@"fmain"]; id<MTLFunction> fragFunc = [fragShaderLib newFunctionWithName:@"fmain"];
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc, MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc,

View File

@ -5,7 +5,7 @@
#include "boo/graphicsdev/Metal.hpp" #include "boo/graphicsdev/Metal.hpp"
#include "CocoaCommon.hpp" #include "CocoaCommon.hpp"
#include <LogVisor/LogVisor.hpp> #include "logvisor/logvisor.hpp"
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
#error ARC Required #error ARC Required
@ -22,7 +22,7 @@ namespace boo {class ApplicationCocoa;}
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::ApplicationCocoa"); static logvisor::Module Log("boo::ApplicationCocoa");
IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx,
MetalContext* metalCtx, uint32_t sampleCount); MetalContext* metalCtx, uint32_t sampleCount);
@ -91,11 +91,11 @@ public:
{ {
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice(); m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue]; m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue];
Log.report(LogVisor::Info, "using Metal renderer"); Log.report(logvisor::Info, "using Metal renderer");
break; break;
} }
if (!m_metalCtx.m_dev) if (!m_metalCtx.m_dev)
Log.report(LogVisor::Info, "using OpenGL renderer"); Log.report(logvisor::Info, "using OpenGL renderer");
#else #else
Log.report(LogVisor::Info, "using OpenGL renderer"); Log.report(LogVisor::Info, "using OpenGL renderer");
#endif #endif

View File

@ -165,7 +165,7 @@ class GraphicsContextCocoaMetal;
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::WindowCocoa"); static logvisor::Module Log("boo::WindowCocoa");
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent); IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent);
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
IGraphicsContext* parent); IGraphicsContext* parent);
@ -223,7 +223,7 @@ public:
{ {
m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this]; m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this];
if (!m_nsContext) if (!m_nsContext)
Log.report(LogVisor::FatalError, "unable to make new NSOpenGLView"); Log.report(logvisor::Fatal, "unable to make new NSOpenGLView");
[(__bridge NSWindow*)(void*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext]; [(__bridge NSWindow*)(void*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink); CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this); CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
@ -257,7 +257,7 @@ public:
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[int(m_pf)]]; NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[int(m_pf)]];
m_mainCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:[m_nsContext openGLContext]]; m_mainCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:[m_nsContext openGLContext]];
if (!m_mainCtx) if (!m_mainCtx)
Log.report(LogVisor::FatalError, "unable to make main NSOpenGLContext"); Log.report(logvisor::Fatal, "unable to make main NSOpenGLContext");
} }
[m_mainCtx makeCurrentContext]; [m_mainCtx makeCurrentContext];
return m_dataFactory; return m_dataFactory;
@ -270,7 +270,7 @@ public:
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[int(m_pf)]]; NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_TABLE[int(m_pf)]];
m_loadCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:[m_nsContext openGLContext]]; m_loadCtx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:[m_nsContext openGLContext]];
if (!m_loadCtx) if (!m_loadCtx)
Log.report(LogVisor::FatalError, "unable to make load NSOpenGLContext"); Log.report(logvisor::Fatal, "unable to make load NSOpenGLContext");
} }
[m_loadCtx makeCurrentContext]; [m_loadCtx makeCurrentContext];
return m_dataFactory; return m_dataFactory;
@ -380,7 +380,7 @@ public:
MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow]; MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow];
m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this]; m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this];
if (!m_nsContext) if (!m_nsContext)
Log.report(LogVisor::FatalError, "unable to make new NSView for Metal"); Log.report(logvisor::Fatal, "unable to make new NSView for Metal");
w.m_metalLayer = (CAMetalLayer*)m_nsContext.layer; w.m_metalLayer = (CAMetalLayer*)m_nsContext.layer;
[(__bridge NSWindow*)(void*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext]; [(__bridge NSWindow*)(void*)m_parentWindow->getPlatformHandle() setContentView:m_nsContext];
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink); CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);