Permalink
Browse files

-Add: digitized sound output for old Mac OS X implementation

using CoreAudio / AudioUnits
  • Loading branch information...
miniupnp committed May 25, 2018
1 parent 81ceb54 commit a06997007c9a213c9195f00b2446ea1612f483b2
Showing with 175 additions and 0 deletions.
  1. +1 −0 config.lib
  2. +4 −0 source.list
  3. +169 −0 src/audio/dsp_osx.c
  4. +1 −0 src/audio/midi_osx.c
View
@@ -947,6 +947,7 @@ make_cflags_and_ldflags() {
if [ -z "$sdl2_config" ] && [ -z "$sdl_config" ] ; then
LDFLAGS="$LDFLAGS -Wl,-framework,ApplicationServices"
LDFLAGS="$LDFLAGS -Wl,-framework,Carbon"
LDFLAGS="$LDFLAGS -Wl,-framework,CoreAudio"
fi
if [ "$enable_universal" = "0" ]; then
View
@@ -26,7 +26,11 @@ audio/midi_atari.c
#if SDL2
audio/dsp_sdl.c
#else
#if OSX
audio/dsp_osx.c
#else
audio/dsp_none.c
#endif
#endif
#endif
#endif
View
@@ -0,0 +1,169 @@
/* AudioUnit */
#if defined(__ALTIVEC__) && !defined(MAC_OS_X_VERSION_10_5)
/* to circumvent a bug in Mac OS X 10.4 SDK */
#define vector __vector
#include <CoreServices/CoreServices.h>
#undef vector
#endif
#include <AudioUnit/AudioUnit.h>
#include "types.h"
#include "dsp.h"
#include "../os/error.h"
#include "../os/endian.h"
static AudioUnit outputAudioUnit;
uint32 remaining_len = 0;
const uint8 * current_data;
static OSStatus audioCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
UInt32 i, len;
char * ptr;
Debug("audioCallback(%p, %p, %p, %u, %u, %p)\n",
inRefCon, ioActionFlags, inTimeStamp, (unsigned)inBusNumber, (unsigned)inNumberFrames, ioData);
for (i = 0; i < ioData->mNumberBuffers; i++) {
len = ioData->mBuffers[i].mDataByteSize;
ptr = ioData->mBuffers[i].mData;
if (remaining_len == 0 || i > 0) {
memset(ptr, 0x80, len);
} else if (remaining_len < len) {
memcpy(ptr, current_data, remaining_len);
ptr += remaining_len;
len -= remaining_len;
remaining_len = 0;
memset(ptr, 0x80, len);
} else {
memcpy(ptr, current_data, len);
remaining_len -= len;
current_data += len;
}
}
return noErr;
}
void DSP_Play(const uint8 *data)
{
AudioStreamBasicDescription format;
UInt32 size = sizeof(format);
OSStatus err;
uint32 len;
DSP_Stop();
format.mChannelsPerFrame = 1; /* MONO */
/*format.mChannelsPerFrame = 2;*/ /* STEREO */
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;
format.mBitsPerChannel = 8;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = format.mBitsPerChannel * format.mChannelsPerFrame / 8;
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
data += READ_LE_UINT16(data + 20); /* skip Create Voice File header */
len = (READ_LE_UINT32(data) >> 8) - 2;
data += 4;
format.mSampleRate = 1000000 / (256 - data[0]);
data += 2;
/* Set the input format of the audio unit. */
err = AudioUnitSetProperty(outputAudioUnit,
kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
0, &format, sizeof(format));
if (err != noErr) Warning("AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed\n");
current_data = data;
remaining_len = len;
err = AudioOutputUnitStart (outputAudioUnit);
if (err != noErr) Warning("AudioOutputUnitStart() failed\n");
}
void DSP_Stop(void)
{
OSStatus result = AudioOutputUnitStop (outputAudioUnit);
if (result != noErr) Warning("AudioOutputUnitStop() failed\n");
}
uint8 DSP_GetStatus(void)
{
if (remaining_len > 0) return 2; /* playing */
return 0; /* not playing */
}
bool DSP_Init(void)
{
OSStatus result = noErr;
Component comp;
ComponentDescription desc;
struct AURenderCallbackStruct callback;
/* Locate the default output audio unit */
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
comp = FindNextComponent (NULL, &desc);
if (comp == NULL) {
Warning("Failed to start CoreAudio: FindNextComponent returned NULL\n");
return false;
}
result = OpenAComponent (comp, &outputAudioUnit);
if (result != noErr) {
Warning("OpenAComponent() failed\n");
return false;
}
result = AudioUnitInitialize (outputAudioUnit);
if (result != noErr) {
Warning("AudioUnitInitialize() failed\n");
return false;
}
/* Set the audio callback */
callback.inputProc = audioCallback;
callback.inputProcRefCon = NULL;
result = AudioUnitSetProperty(outputAudioUnit,
kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
0, &callback, sizeof(callback));
if (result != noErr) {
Warning("AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed\n");
return false;
}
return true;
}
void DSP_Uninit(void)
{
OSStatus result = noErr;
struct AURenderCallbackStruct callback;
DSP_Stop();
/* Remove the input callback */
callback.inputProc = 0;
callback.inputProcRefCon = 0;
result = AudioUnitSetProperty(outputAudioUnit,
kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
0, &callback, sizeof(callback));
if (result != noErr) {
Warning("AudioUnitSetProperty(kAudioUnitProperty_SetInputCallback) failed\n");
}
result = CloseComponent(outputAudioUnit);
if (result != noErr) {
Warning("CloseComponent() failed\n");
}
}
View
@@ -11,6 +11,7 @@
#include <AudioToolbox/AudioToolbox.h>
#include "types.h"
#include "midi.h"
#include "../os/error.h"
#if defined(AUDIO_TOOLBOX_VERSION) && (AUDIO_TOOLBOX_VERSION >= 0x0105)
/* Use the new functions in favor of deprecated ones from OS X 10.5 onward */

0 comments on commit a069970

Please sign in to comment.