⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drv_osx.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 2 页
字号:
                                      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 + -