📄 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_osxMIKMODAPI 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#elseMISSING(drv_osx);#endif /* DRV_OSX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -