Added new Audio Unit MIDI player, currently not in use.

CQTexperiment
Chris Moeller 2016-01-11 01:36:41 -08:00
parent 5bd098fa88
commit fed76e9a49
3 changed files with 332 additions and 0 deletions

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
8398F2E01C438C7D00EB9639 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8398F2DF1C438C7D00EB9639 /* AudioUnit.framework */; };
839CA224180D902100553DBA /* midi_processing.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83B066E0180D56BA008E3612 /* midi_processing.framework */; };
83B0668B180D5668008E3612 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B0668A180D5668008E3612 /* Cocoa.framework */; };
83B06695180D5668008E3612 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83B06693180D5668008E3612 /* InfoPlist.strings */; };
@ -24,6 +25,7 @@
83B06722180D70FE008E3612 /* MIDIDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83B06721180D70FE008E3612 /* MIDIDecoder.mm */; };
83C35702180EDB74007E9DF0 /* MIDIContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83C35700180EDB74007E9DF0 /* MIDIContainer.mm */; };
83C35705180EDD1C007E9DF0 /* MIDIMetadataReader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83C35703180EDD1C007E9DF0 /* MIDIMetadataReader.mm */; };
83E973471C4378880007F413 /* AUPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E973451C4378880007F413 /* AUPlayer.mm */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -72,6 +74,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
8398F2DF1C438C7D00EB9639 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
83B06687180D5668008E3612 /* MIDI.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MIDI.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
83B0668A180D5668008E3612 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
83B0668D180D5668008E3612 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@ -99,6 +102,8 @@
83C35701180EDB74007E9DF0 /* MIDIContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIDIContainer.h; sourceTree = "<group>"; };
83C35703180EDD1C007E9DF0 /* MIDIMetadataReader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MIDIMetadataReader.mm; sourceTree = "<group>"; };
83C35704180EDD1C007E9DF0 /* MIDIMetadataReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIDIMetadataReader.h; sourceTree = "<group>"; };
83E973451C4378880007F413 /* AUPlayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AUPlayer.mm; sourceTree = "<group>"; };
83E973461C4378880007F413 /* AUPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AUPlayer.h; sourceTree = "<group>"; };
83FAF8A618ADD60100057CAF /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -107,6 +112,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8398F2E01C438C7D00EB9639 /* AudioUnit.framework in Frameworks */,
83B0670F180D6F7F008E3612 /* libbass.dylib in Frameworks */,
83B06701180D5747008E3612 /* midi_processing.framework in Frameworks */,
83B06710180D6F7F008E3612 /* libbassmidi.dylib in Frameworks */,
@ -137,6 +143,7 @@
83B06689180D5668008E3612 /* Frameworks */ = {
isa = PBXGroup;
children = (
8398F2DF1C438C7D00EB9639 /* AudioUnit.framework */,
83B06714180D6FC8008E3612 /* libbass_mpc.dylib */,
83B06715180D6FC8008E3612 /* libbassflac.dylib */,
83B06716180D6FC8008E3612 /* libbassopus.dylib */,
@ -163,6 +170,8 @@
83B06690180D5668008E3612 /* MIDI */ = {
isa = PBXGroup;
children = (
83E973451C4378880007F413 /* AUPlayer.mm */,
83E973461C4378880007F413 /* AUPlayer.h */,
83FAF8A618ADD60100057CAF /* PlaylistController.h */,
83C35703180EDD1C007E9DF0 /* MIDIMetadataReader.mm */,
83C35704180EDD1C007E9DF0 /* MIDIMetadataReader.h */,
@ -280,6 +289,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
83E973471C4378880007F413 /* AUPlayer.mm in Sources */,
83B06709180D64DA008E3612 /* MIDIPlayer.cpp in Sources */,
83B06722180D70FE008E3612 /* MIDIDecoder.mm in Sources */,
83C35702180EDB74007E9DF0 /* MIDIContainer.mm in Sources */,

View File

@ -0,0 +1,46 @@
#ifndef __AUPlayer_h__
#define __AUPlayer_h__
#include "MIDIPlayer.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>
class AUPlayer : public MIDIPlayer
{
public:
// zero variables
AUPlayer();
// close, unload
virtual ~AUPlayer();
// configuration
void showDialog();
typedef void (*callback)(const char * name);
void enumComponents(callback cbEnum);
void setComponent(const char * name);
protected:
virtual void send_event(uint32_t b);
virtual void render(float * out, unsigned long count);
virtual void shutdown();
virtual bool startup();
private:
AudioTimeStamp mTimeStamp;
AudioUnit samplerUnit[3];
AudioBufferList *bufferList;
float *audioBuffer;
char *mComponentName;
};
#endif

View File

@ -0,0 +1,276 @@
#include "AUPlayer.h"
#include <stdlib.h>
#define SF2PACK
#define _countof(arr) (sizeof(arr) / sizeof((arr)[0]))
AUPlayer::AUPlayer() : MIDIPlayer()
{
samplerUnit[0] = NULL;
samplerUnit[1] = NULL;
samplerUnit[2] = NULL;
bufferList = NULL;
audioBuffer = NULL;
mComponentName = NULL;
}
AUPlayer::~AUPlayer()
{
shutdown();
}
void AUPlayer::send_event(uint32_t b)
{
if (!(b & 0x80000000))
{
unsigned char event[ 3 ];
event[ 0 ] = (unsigned char)b;
event[ 1 ] = (unsigned char)( b >> 8 );
event[ 2 ] = (unsigned char)( b >> 16 );
unsigned port = (b >> 24) & 0x7F;
if ( port > 2 ) port = 2;
MusicDeviceMIDIEvent(samplerUnit[port], event[0], event[1], event[2], 0);
}
else
{
uint32_t n = b & 0xffffff;
const uint8_t * data;
std::size_t size, port;
mSysexMap.get_entry( n, data, size, port );
if ( port > 2 ) port = 2;
MusicDeviceSysEx(samplerUnit[port], data, (UInt32) size);
if ( port == 0 )
{
MusicDeviceSysEx(samplerUnit[1], data, (UInt32) size);
MusicDeviceSysEx(samplerUnit[2], data, (UInt32) size);
}
}
}
void AUPlayer::render(float * out, unsigned long count)
{
float *ptrL, *ptrR;
while (count)
{
unsigned long todo = count;
if (todo > 512)
todo = 512;
memset(out, 0, todo * sizeof(float) * 2);
for (unsigned long i = 0; i < 3; ++i)
{
AudioUnitRenderActionFlags ioActionFlags = 0;
UInt32 numberFrames = (UInt32) todo;
for (unsigned long j = 0; j < 2; j++)
{
bufferList->mBuffers[j].mNumberChannels = 1;
bufferList->mBuffers[j].mDataByteSize = (UInt32) (todo * sizeof(float));
bufferList->mBuffers[j].mData = audioBuffer + j * 512;
memset(bufferList->mBuffers[j].mData, 0, todo * sizeof(float));
}
AudioUnitRender(samplerUnit[i], &ioActionFlags, &mTimeStamp, 0, numberFrames, bufferList);
ptrL = (float *) bufferList->mBuffers[0].mData;
ptrR = (float *) bufferList->mBuffers[1].mData;
for (unsigned long j = 0; j < todo; ++j)
{
out[j * 2 + 0] += ptrL[j];
out[j * 2 + 1] += ptrR[j];
}
}
mTimeStamp.mSampleTime += (Float64) todo;
out += todo * 2;
count -= todo;
}
}
void AUPlayer::shutdown()
{
if ( samplerUnit[2] )
{
AudioUnitUninitialize( samplerUnit[2] );
AudioComponentInstanceDispose( samplerUnit[2] );
samplerUnit[2] = NULL;
}
if ( samplerUnit[1] )
{
AudioUnitUninitialize( samplerUnit[1] );
AudioComponentInstanceDispose( samplerUnit[1] );
samplerUnit[1] = NULL;
}
if ( samplerUnit[0] )
{
AudioUnitUninitialize( samplerUnit[0] );
AudioComponentInstanceDispose( samplerUnit[0] );
samplerUnit[0] = NULL;
}
if (audioBuffer)
{
free(audioBuffer);
audioBuffer = NULL;
}
if (bufferList)
{
free(bufferList);
bufferList = NULL;
}
}
void AUPlayer::enumComponents(callback cbEnum)
{
AudioComponentDescription cd = {0};
cd.componentType = kAudioUnitType_MusicDevice;
AudioComponent comp = NULL;
const char * bytes;
char bytesBuffer[512];
comp = AudioComponentFindNext(comp, &cd);
while (comp != NULL)
{
CFStringRef cfName;
AudioComponentCopyName(comp, &cfName);
bytes = CFStringGetCStringPtr(cfName, kCFStringEncodingUTF8);
if (!bytes)
{
CFStringGetCString(cfName, bytesBuffer, sizeof(bytesBuffer) - 1, kCFStringEncodingUTF8);
bytes = bytesBuffer;
}
cbEnum(bytes);
CFRelease(cfName);
comp = AudioComponentFindNext(comp, &cd);
}
}
void AUPlayer::setComponent(const char *name)
{
if (mComponentName)
{
free(mComponentName);
mComponentName = NULL;
}
size_t size = strlen(name) + 1;
mComponentName = (char *) malloc(size);
memcpy(mComponentName, name, size);
}
bool AUPlayer::startup()
{
if (bufferList) return true;
AudioComponentDescription cd = {0};
cd.componentType = kAudioUnitType_MusicDevice;
AudioComponent comp = NULL;
const char * pComponentName = mComponentName;
const char * bytes;
char bytesBuffer[512];
comp = AudioComponentFindNext(comp, &cd);
if (pComponentName == NULL)
{
pComponentName = "Roland: SOUND Canvas VA";
//pComponentName = "Apple: DLSMusicDevice";
}
while (comp != NULL)
{
CFStringRef cfName;
AudioComponentCopyName(comp, &cfName);
bytes = CFStringGetCStringPtr(cfName, kCFStringEncodingUTF8);
if (!bytes)
{
CFStringGetCString(cfName, bytesBuffer, sizeof(bytesBuffer) - 1, kCFStringEncodingUTF8);
bytes = bytesBuffer;
}
if (!strcmp(bytes, pComponentName))
{
CFRelease(cfName);
break;
}
CFRelease(cfName);
comp = AudioComponentFindNext(comp, &cd);
}
if (!comp)
return false;
OSStatus error;
for (int i = 0; i < 3; i++)
{
error = AudioComponentInstanceNew(comp, &samplerUnit[i]);
if (error != noErr)
return false;
Float64 sampleRateIn = 0, sampleRateOut = 0;
UInt32 sampleRateSize = sizeof (sampleRateIn);
const Float64 sr = uSampleRate;
AudioUnitGetProperty(samplerUnit[i], kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sampleRateIn, &sampleRateSize);
if (sampleRateIn != sr)
AudioUnitSetProperty(samplerUnit[i], kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sr, sizeof (sr));
AudioUnitGetProperty (samplerUnit[i], kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRateOut, &sampleRateSize);
if (sampleRateOut != sr)
AudioUnitSetProperty (samplerUnit[i], kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, i, &sr, sizeof (sr));
AudioUnitReset (samplerUnit[i], kAudioUnitScope_Input, 0);
AudioUnitReset (samplerUnit[i], kAudioUnitScope_Output, 0);
AudioUnitReset (samplerUnit[i], kAudioUnitScope_Global, 0);
{
AudioStreamBasicDescription stream = { 0 };
stream.mSampleRate = uSampleRate;
stream.mFormatID = kAudioFormatLinearPCM;
stream.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagsNativeEndian;
stream.mFramesPerPacket = 1;
stream.mBytesPerPacket = 4;
stream.mBytesPerFrame = 4;
stream.mBitsPerChannel = 32;
stream.mChannelsPerFrame = 2;
AudioUnitSetProperty (samplerUnit[i], kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &stream, sizeof (stream));
AudioUnitSetProperty (samplerUnit[i], kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &stream, sizeof (stream));
}
error = AudioUnitInitialize(samplerUnit[i]);
if (error != noErr)
return false;
}
bufferList = (AudioBufferList *) calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer));
if (!bufferList)
return false;
audioBuffer = (float *) malloc(1024 * sizeof(float));
if (!audioBuffer)
return false;
bufferList->mNumberBuffers = 2;
memset(&mTimeStamp, 0, sizeof(mTimeStamp));
mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
return true;
}