📄 drv_osx.c
字号:
AudioBufferList *outOutputData,
const AudioTimeStamp *inOutputTime,
void *inClientData)
{
register float *myOutBuffer = (float *) outOutputData->mBuffers[0].mData;
register float *myInBuffer;
register UInt32 i;
#if USE_FILL_THREAD
pthread_mutex_lock (&gBufferMutex);
#if DEBUG_TRACE_THREADS
fprintf(stderr,"playing buffer #%d\n", gCurrentPlayBuffer);
#endif
myInBuffer = (float *) gSoundBackBuffer[gCurrentPlayBuffer];
if (++gCurrentPlayBuffer >= NUMBER_BACK_BUFFERS)
gCurrentPlayBuffer = 0;
// ... perhaps wash the windshield
pthread_cond_signal (&gBufferCondition);
pthread_mutex_unlock (&gBufferMutex);
#else
// avoid copy, if no conversion needed
myInBuffer = (gBufferMono2Stereo) ? (float *) gSoundBuffer : myOutBuffer;
FILL_BUFFER( myInBuffer, gInBufferSize);
#endif /* USE_FILL_THREAD */
if (gBufferMono2Stereo)
{
for (i = 0; i < SOUND_BUFFER_SIZE >> 1; i++)
{
myOutBuffer[1] = myOutBuffer[0] = *myInBuffer++;
myOutBuffer+=2;
}
}
else if (myInBuffer != myOutBuffer)
{
for (i = 0; i < SOUND_BUFFER_SIZE; i++)
{
*myOutBuffer++ = *myInBuffer++;
}
}
return 0;
}
//________________________________________________________________________________________OSX_IsPresent()
static BOOL OSX_IsPresent (void)
{
// bad boy... have to find a better way!
if (!AudioHardwareGetProperty)
return (0);
return (1);
}
//_____________________________________________________________________________________________OSX_Init()
static BOOL OSX_Init (void)
{
AudioStreamBasicDescription mySoundBasicDescription;
UInt32 myPropertySize, myBufferByteCount;
// get the device...
myPropertySize = sizeof (gSoundDeviceID);
CHECK_ERROR
(
MMERR_DETECTING_DEVICE,
AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,
&myPropertySize, &gSoundDeviceID)
);
if (gSoundDeviceID == kAudioDeviceUnknown)
{
_mm_errno = MMERR_OSX_UNKNOWN_DEVICE;
return(1);
}
// get the device format...
myPropertySize = sizeof (mySoundBasicDescription);
CHECK_ERROR
(
MMERR_OSX_BAD_PROPERTY,
AudioDeviceGetProperty (gSoundDeviceID, 0, 0, kAudioDevicePropertyStreamFormat,
&myPropertySize, &mySoundBasicDescription)
);
// set up basic md_mode, just to be secure...
md_mode |= DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;
// try the selected mix frequency, if failure, fall back to native frequency...
if (mySoundBasicDescription.mSampleRate != md_mixfreq)
{
mySoundBasicDescription.mSampleRate = md_mixfreq;
SET_PROPS ();
md_mixfreq = mySoundBasicDescription.mSampleRate;
}
// try selected channels, if failure select native channels...
switch (md_mode & DMODE_STEREO)
{
case 0:
if (mySoundBasicDescription.mChannelsPerFrame != 1)
{
mySoundBasicDescription.mChannelsPerFrame = 1;
SET_PROPS ();
SET_STEREO ();
}
break;
case 1:
if (mySoundBasicDescription.mChannelsPerFrame != 2)
{
mySoundBasicDescription.mChannelsPerFrame = 2;
SET_PROPS();
SET_STEREO();
}
break;
}
// linear PCM is required...
if (mySoundBasicDescription.mFormatID != kAudioFormatLinearPCM)
{
_mm_errno = MMERR_OSX_UNSUPPORTED_FORMAT;
return(1);
}
// prepare the buffers...
if (gBufferMono2Stereo)
{
gInBufferSize = SOUND_BUFFER_SIZE >> 1;
}
else
{
gInBufferSize = SOUND_BUFFER_SIZE;
}
if (md_mode & DMODE_FLOAT)
{
gInBufferSize *= sizeof(float);
gAudioIOProc = OSX_AudioIOProcFloat;
}
else if (md_mode & DMODE_16BITS)
{
gInBufferSize *= sizeof(SInt16);
gAudioIOProc = OSX_AudioIOProc16Bit;
}
else
{
gInBufferSize *= sizeof(UInt8);
gAudioIOProc = OSX_AudioIOProc8Bit;
}
myBufferByteCount = SOUND_BUFFER_SIZE * sizeof(float);
CHECK_ERROR
(
MMERR_OSX_BUFFER_ALLOC,
AudioDeviceSetProperty (gSoundDeviceID, NULL, 0, 0, kAudioDevicePropertyBufferSize,
sizeof(myBufferByteCount), &myBufferByteCount)
);
// add our audio IO procedure....
CHECK_ERROR
(
MMERR_OSX_ADD_IO_PROC,
AudioDeviceAddIOProc (gSoundDeviceID, gAudioIOProc, NULL)
);
gIOProcIsInstalled = 1;
#if !USE_FILL_THREAD
// get the buffer memory...
if ((gSoundBuffer = malloc(gInBufferSize)) == NULL)
{
_mm_errno = MMERR_OUT_OF_MEMORY;
return (1);
}
#else
// some thread init...
if (pthread_mutex_init (&gBufferMutex, NULL) ||
pthread_cond_init (&gBufferCondition, NULL))
{
_mm_errno = MMERR_OSX_PTHREAD;
return (1);
}
{
int i;
for (i = 0; i < NUMBER_BACK_BUFFERS; i++)
if ((gSoundBackBuffer[i] = malloc(gInBufferSize)) == NULL)
{
_mm_errno = MMERR_OUT_OF_MEMORY;
return (1);
}
gCurrentPlayBuffer = 0;
gCurrentFillBuffer = 0;
}
#endif /* USE_FILL_THREAD */
// last not least init mikmod...
return VC_Init ();
}
//_____________________________________________________________________________________________OSX_Exit()
static void OSX_Exit (void)
{
if (gDeviceHasStarted)
{
// stop the audio device...
AudioDeviceStop (gSoundDeviceID, gAudioIOProc);
gDeviceHasStarted = 0;
#if USE_FILL_THREAD
// finish the fill buffer thread off...
pthread_mutex_lock (&gBufferMutex);
gExitBufferFillThread = 1;
pthread_mutex_unlock (&gBufferMutex);
pthread_cond_signal(&gBufferCondition);
pthread_join (gBufferFillThread, NULL);
}
// destroy other thread related stuff...
pthread_mutex_destroy (&gBufferMutex);
pthread_cond_destroy (&gBufferCondition);
#else
}
#endif /* USE_FILL_THREAD */
// remove the audio IO proc...
if (gIOProcIsInstalled)
{
AudioDeviceRemoveIOProc (gSoundDeviceID, gAudioIOProc);
gIOProcIsInstalled = 0;
}
#if !USE_FILL_THREAD
// free up the sound buffer...
if (gSoundBuffer)
{
free (gSoundBuffer);
gSoundBuffer = NULL;
}
#else
{
int i;
for ( i = 0; i < NUMBER_BACK_BUFFERS; i++ )
{
// free up the back buffer...
if (gSoundBackBuffer[i])
{
free (gSoundBackBuffer[i]);
gSoundBackBuffer[i] = NULL;
}
}
}
#endif /* USE_FILL_THREAD */
VC_Exit ();
}
//________________________________________________________________________________________OSX_PlayStart()
static BOOL OSX_PlayStart (void)
{
// start virtch...
if (VC_PlayStart ())
{
return (1);
}
// just for security: audio device already playing?
if (gDeviceHasStarted) return (0);
#if USE_FILL_THREAD
// start the buffer fill thread...
gExitBufferFillThread = 0;
if (pthread_create (&gBufferFillThread, NULL, OSX_FillBuffer , NULL))
{
_mm_errno = MMERR_OSX_PTHREAD;
return (1);
}
#endif /* USE_FILL_THREAD */
// start the audio IO Proc...
if (AudioDeviceStart (gSoundDeviceID, gAudioIOProc))
{
_mm_errno = MMERR_OSX_DEVICE_START;
return (1);
}
gDeviceHasStarted = 1;
return (0);
}
//_________________________________________________________________________________________OSX_PlayStop()
static void OSX_PlayStop (void)
{
if (gDeviceHasStarted)
{
// stop the audio IO Proc...
AudioDeviceStop (gSoundDeviceID, gAudioIOProc);
gDeviceHasStarted = 0;
#if USE_FILL_THREAD
// finish the fill buffer thread off...
pthread_mutex_lock (&gBufferMutex);
gExitBufferFillThread = 1;
pthread_mutex_unlock (&gBufferMutex);
pthread_cond_signal (&gBufferCondition);
pthread_join (gBufferFillThread, NULL);
#endif /* USE_FILL_THREAD */
}
// finally tell virtch that playback has stopped...
VC_PlayStop ();
}
//___________________________________________________________________________________________OSX_Update()
static void OSX_Update (void)
{
// do nothing...
}
//________________________________________________________________________________________________drv_osx
MIKMODAPI MDRIVER drv_osx={
NULL,
"CoreAudio Driver",
"CoreAudio Driver v2.1",
0,255,
"osx",
NULL,
NULL,
OSX_IsPresent,
VC_SampleLoad,
VC_SampleUnload,
VC_SampleSpace,
VC_SampleLength,
OSX_Init,
OSX_Exit,
NULL,
VC_SetNumVoices,
OSX_PlayStart,
OSX_PlayStop,
OSX_Update,
NULL,
VC_VoiceSetVolume,
VC_VoiceGetVolume,
VC_VoiceSetFrequency,
VC_VoiceGetFrequency,
VC_VoiceSetPanning,
VC_VoiceGetPanning,
VC_VoicePlay,
VC_VoiceStop,
VC_VoiceStopped,
VC_VoiceGetPosition,
VC_VoiceRealVolume
};
//____________________________________________________________________________________________________EOF
#else
MISSING(drv_osx);
#endif /* DRV_OSX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -