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;
AudioQueueRef m_queue = nullptr;
AudioQueueBufferRef m_buffers[3];
size_t m_bufferFrames = 2048;
size_t m_bufferFrames = 1024;
size_t m_frameSize;
const ChannelMap& channelMap() const {return m_map;}
@ -48,7 +48,7 @@ struct AQSAudioVoice : IAudioVoice
{
AQSAudioVoice* voice = static_cast<AQSAudioVoice*>(inUserData);
voice->m_callbackBuf = inBuffer;
voice->m_cb->needsNextBuffer(voice, voice->m_bufferFrames);
voice->m_cb->needsNextBuffer(*voice, voice->m_bufferFrames);
voice->m_callbackBuf = nullptr;
}
@ -80,73 +80,81 @@ struct AQSAudioVoice : IAudioVoice
}
if (err)
{
Log.report(logvisor::Error, "unable to create output audio queue");
Log.report(logvisor::Fatal, "unable to create output audio queue");
return;
}
AudioChannelLayout layout;
UInt32 layoutSz = sizeof(layout);
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz))
if (chCount > 2)
{
Log.report(logvisor::Error, "unable to get channel layout from audio queue");
return;
}
switch (layout.mChannelLayoutTag)
{
case kAudioChannelLayoutTag_UseChannelDescriptions:
m_map.m_channelCount = layout.mNumberChannelDescriptions;
for (int i=0 ; i<layout.mNumberChannelDescriptions ; ++i)
AudioChannelLayout layout;
UInt32 layoutSz = sizeof(layout);
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz))
{
AudioChannel ch = AQSChannelToBooChannel(layout.mChannelDescriptions[i].mChannelLabel);
m_map.m_channels[i] = ch;
Log.report(logvisor::Fatal, "unable to get channel layout from audio queue");
return;
}
break;
case kAudioChannelLayoutTag_UseChannelBitmap:
if ((layout.mChannelBitmap & kAudioChannelBit_Left) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_Right) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontRight;
if ((layout.mChannelBitmap & kAudioChannelBit_Center) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontCenter;
if ((layout.mChannelBitmap & kAudioChannelBit_LFEScreen) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::LFE;
if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurround) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_RightSurround) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearRight;
if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurroundDirect) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_RightSurroundDirect) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideRight;
break;
case kAudioChannelLayoutTag_Stereo:
case kAudioChannelLayoutTag_StereoHeadphones:
m_map.m_channelCount = 2;
m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channels[1] = AudioChannel::FrontRight;
break;
case kAudioChannelLayoutTag_Quadraphonic:
m_map.m_channelCount = 4;
m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channels[1] = AudioChannel::FrontRight;
m_map.m_channels[2] = AudioChannel::RearLeft;
m_map.m_channels[3] = AudioChannel::RearRight;
break;
case kAudioChannelLayoutTag_Pentagonal:
m_map.m_channelCount = 5;
m_map.m_channels[0] = AudioChannel::FrontLeft;
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::Error, "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;
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);
m_map.m_channels[i] = ch;
}
break;
case kAudioChannelLayoutTag_UseChannelBitmap:
if ((layout.mChannelBitmap & kAudioChannelBit_Left) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_Right) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontRight;
if ((layout.mChannelBitmap & kAudioChannelBit_Center) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::FrontCenter;
if ((layout.mChannelBitmap & kAudioChannelBit_LFEScreen) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::LFE;
if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurround) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_RightSurround) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::RearRight;
if ((layout.mChannelBitmap & kAudioChannelBit_LeftSurroundDirect) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideLeft;
if ((layout.mChannelBitmap & kAudioChannelBit_RightSurroundDirect) != 0)
m_map.m_channels[m_map.m_channelCount++] = AudioChannel::SideRight;
break;
case kAudioChannelLayoutTag_Stereo:
case kAudioChannelLayoutTag_StereoHeadphones:
m_map.m_channelCount = 2;
m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channels[1] = AudioChannel::FrontRight;
break;
case kAudioChannelLayoutTag_Quadraphonic:
m_map.m_channelCount = 4;
m_map.m_channels[0] = AudioChannel::FrontLeft;
m_map.m_channels[1] = AudioChannel::FrontRight;
m_map.m_channels[2] = AudioChannel::RearLeft;
m_map.m_channels[3] = AudioChannel::RearRight;
break;
case kAudioChannelLayoutTag_Pentagonal:
m_map.m_channelCount = 5;
m_map.m_channels[0] = AudioChannel::FrontLeft;
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)
@ -155,7 +163,7 @@ struct AQSAudioVoice : IAudioVoice
for (int i=0 ; i<3 ; ++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);
m_queue = nullptr;
return;
@ -166,7 +174,7 @@ struct AQSAudioVoice : IAudioVoice
for (unsigned i=0 ; i<3 ; ++i)
{
m_primeBuf = i;
m_cb->needsNextBuffer(this, m_bufferFrames);
m_cb->needsNextBuffer(*this, m_bufferFrames);
}
AudioQueuePrime(m_queue, 0, nullptr);
}
@ -206,6 +214,56 @@ struct AQSAudioVoice : IAudioVoice
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,
unsigned sampleRate,
IAudioVoiceCallback* cb)
@ -216,6 +274,8 @@ struct AQSAudioVoiceAllocator : IAudioVoiceAllocator
return {};
return ret;
}
void pumpVoices() {}
};
std::unique_ptr<IAudioVoiceAllocator> NewAudioVoiceAllocator()

View File

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

View File

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

View File

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