コード例 #1
0
ファイル: AUDSimpleAudio.cpp プロジェクト: basecq/thug
void AUDSimpleAudioChangePlayback(const u32 *playMaskArray,u32 numMasks)
	{
	u32		i,b;
	BOOL	old = OSDisableInterrupts();
	
	audioPlayMaskArray = playMaskArray;
	audioNumPlayMasks = numMasks;
	
	// Any playback mask specified?
	if (audioNumPlayMasks != 0)
		{
		// Yes. Count the active voices...
		audioNumActiveVoices = 0;
		
		for(i=0; i<numMasks; i++)
			{
			for(b=0; b<32; b++)
				{
				if (audioPlayMaskArray[i] & (1<<b))
					audioNumActiveVoices++;
				}
			}
		
        // So, did we have too much?
		ASSERT(audioNumActiveVoices <= 2);
		}
	else
		audioNumActiveVoices = audioReadBufferNumChannels;		// Make all active...
	
	OSRestoreInterrupts(old);
	}
コード例 #2
0
/**
 * Release an Uninterruptible Spin Lock.
 *
 * Interrupts will be restored to their previous state before
 * the lock was acquired.
 *
 * \return Returns TRUE if the lock was released.
 */
BOOL
OSUninterruptibleSpinLock_Release(OSSpinLock *spinlock)
{
   if (spinReleaseLock(spinlock)) {
      OSRestoreInterrupts(spinlock->restoreInterruptState);
   }

   return TRUE;
}
コード例 #3
0
ファイル: AUDSimpleAudio.cpp プロジェクト: basecq/thug
/*!
 ******************************************************************************
 * \brief
 *		Stop audio playback without shutting down AI etc.
 *
 ******************************************************************************
 */
void AUDSimpleAudioReset(void)
	{
	BOOL	old;

	old = OSDisableInterrupts();
	
	audioReadBufferWritePos = 0;
	audioReadBufferReadPos = 0;
	
	audioPlayBufferEnabled = FALSE;
		
	OSRestoreInterrupts(old);
	}
コード例 #4
0
ファイル: AUDSimpleAudio.cpp プロジェクト: basecq/thug
/*!
 ******************************************************************************
 * \brief
 *		Shutdown audio decoder and free resources
 *
 ******************************************************************************
 */
void AUDSimpleExitAudioDecoder(void)
	{
	// Yes. Unregister callback & stop AI DMA
	BOOL old = OSDisableInterrupts();
	
	// Register our default AX callback.
	AXRegisterCallback( Sfx::AXUserCBack );
	
	AXSetVoiceState(axVoice[0],AX_PB_STATE_STOP);
	AXSetVoiceState(axVoice[1],AX_PB_STATE_STOP);
	AXFreeVoice(axVoice[0]);
	AXFreeVoice(axVoice[1]);
	
	axVoice[0] = axVoice[1] = NULL;
	
	OSRestoreInterrupts(old);

	// Free allocated resources...
	audio_player.cbFree(audioPlayBuffer[0]);
	audio_player.cbFree(audioReadBuffer);
	}
コード例 #5
0
ファイル: AUDSimpleAudio.cpp プロジェクト: basecq/thug
/*!
 ******************************************************************************
 * \brief
 *		Main audio data decode function.
 *
 *		This function will be used as a callback from the VIDAudioDecode
 *		function or is called directely in case of PCM or ADPCM.
 *
 * \param numChannels
 *		Number of channels present in the sample array
 *
 * \param samples
 *		Array of s16 pointers to the sample data
 *
 * \param sampleNum
 *		Number of samples in the array. All arrays have the same amount
 *		of sample data
 *
 * \param userData
 *		Some user data
 *
 * \return
 *		FALSE if data could not be interpreted properly
 *
 ******************************************************************************
 */
static BOOL audioDecode(u32 numChannels, const s16 **samples, u32 sampleNum, void* _UNUSED(userData))
	{
	u32	 freeSamples;
	u32	 sampleSize;
	u32	 len1;
	BOOL old;
	
	// we can only play mono or stereo!
	ASSERT(numChannels <= 2);

	// Disable IRQs. We must make sure we don't get interrupted by the AI callback.
	old = OSDisableInterrupts();

	// Did the video decoder just jump back to the beginning of the stream?
	if (audio_player.readBuffer[audio_player.decodeIndex].frameNumber < audio_player.lastDecodedFrame)
		{
		// Yes! We have to reset the internal read buffer and disable any audio output
		// until we got new video data to display...
		//
		// Note: we have to reset our buffers because the stream contains more audio data than
		// neccessary to cover a single video frame within the first few frames to accumulate
		// some safety buffer. If the stream would just be allowed to loop we would get an
		// overflow (unless we used up the extra buffer due to read / decode delays) after a few
		// loops...
		//
		AUDSimpleAudioReset();
		}

	// Calculate the read buffer's sample size
	sampleSize = sizeof(s16) * audioReadBufferNumChannels;

	// How many samples could we put into the buffer?
	if (audioReadBufferWritePos >= audioReadBufferReadPos)
	{
		freeSamples = audioReadBufferNumSamples - (audioReadBufferWritePos - audioReadBufferReadPos);

		if( freeSamples < sampleNum )
		{
			OSRestoreInterrupts(old);
			#ifndef FINAL
			OSReport("*** audioDecode: overflow case 1\n");
			#endif
			return FALSE;				// overflow!
		}

		// We might have a two buffer update to do. Check for it...
		if ((len1 = (audioReadBufferNumSamples - audioReadBufferWritePos)) >= sampleNum)
		{
			// No. We got ourselfs a nice, simple single buffer update.
			writeChannelData((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,sampleNum);
		}
		else
		{
			// Dual buffer case
			writeChannelData((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,len1);
            writeChannelData((s16 *)audioReadBuffer,numChannels,samples,len1,sampleNum-len1);
		}
	}
	else
	{
		freeSamples = audioReadBufferReadPos - audioReadBufferWritePos;

		if (freeSamples < sampleNum)
		{
			OSRestoreInterrupts(old);
			#ifndef FINAL
			OSReport("*** audioDecode: overflow case 2\n");
			#endif
			return FALSE;				// overflow!
		}

		// We're save to assume to have a single buffer update in any case...
		writeChannelData((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,sampleNum);
	}

	// Advance write position...
	audioReadBufferWritePos += sampleNum;

	if (audioReadBufferWritePos >= audioReadBufferNumSamples)
		audioReadBufferWritePos -= audioReadBufferNumSamples;

	// We're done with all critical stuff. IRQs may be enabled again...
	OSRestoreInterrupts(old);

	return TRUE;
	}
コード例 #6
0
ファイル: AUDSimpleAudio.cpp プロジェクト: basecq/thug
/*!
 ******************************************************************************
 * \brief
 *		Initialize audio decoder
 *
 *		This function allocates all neccessary memory for the audio processing
 *		and sets the audio decoder into an idle state, waiting for first data.
 *		A file must be opened with the VIDSimplePlayer before calling this
 *		function.
 *
 * \return
 *		FALSE if any problem was detected
 *
 ******************************************************************************
 */
BOOL AUDSimpleInitAudioDecoder(void)
	{
	u32	 		i, ratio;
	BOOL 		old;
	AXPBMIX		axMix[2];
	AXPBVE 		axVE;
	AXPBSRC		axSRC;
	AXPBADDR 	axAddr;
	AXPBADPCM 	axADPCM;

	// Calculate buffer size to allocate proper memry to keep a bit of "extra" audio data around...
	audioReadBufferNumSamples = (u32)((f32)AUD_AUDIO_READAHEADFRAMES * audio_player.audioInfo.vaud.frq);
	audioReadBufferNumChannels = audio_player.audioInfo.vaud.numChannels <= 2 ? audio_player.audioInfo.vaud.numChannels : 2;

	// Allocate read buffer
	audioReadBuffer = audio_player.cbAlloc(audioReadBufferNumSamples * sizeof(s16) * audio_player.audioInfo.vaud.numChannels);
	if (audioReadBuffer == NULL)
		return FALSE;					// error
	
	// Reset ring buffer
	audioReadBufferReadPos = audioReadBufferWritePos = 0;

	// What frquency is best?
	audioPlayBufferFrq = audio_player.audioInfo.vaud.frq;
	
	// Allocate AI playback buffer
	audioPlayBuffer[0] = audio_player.cbAlloc(2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS);
	if (audioPlayBuffer[0] == NULL)
		return FALSE;					// error
	
	for(i=1; i<AUD_AUDIO_NUMAIBUFFERS; i++)
		audioPlayBuffer[i] = (void *)((u32)audioPlayBuffer[i - 1] + (2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES));
	
	// Reset buffer index
	audioPlayBufferWriteIndex = 0;
	
	// We disable AI output for now (logically)
	audioPlayBufferEnabled = FALSE;
	
	// We assume to playback all we get by default
	audioPlayMaskArray = NULL;
	audioNumPlayMasks = 0;
	audioNumActiveVoices = 2;
	
	// Clear out AI buffers to avoid any noise what so ever
	memset(audioPlayBuffer[0],0,2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS);
	DCFlushRange(audioPlayBuffer[0],2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS);
	
	// Init GCN audio system
	old = OSDisableInterrupts();

	axVoice[0] = AXAcquireVoice(AX_PRIORITY_NODROP,NULL,0);
	ASSERT(axVoice[0] != NULL);
	axVoice[1] = AXAcquireVoice(AX_PRIORITY_NODROP,NULL,0);
	ASSERT(axVoice[1] != NULL);

	memset(&axMix[0],0,sizeof(axMix[0]));
	axMix[0].vL = 0x7FFF;
	memset(&axMix[1],0,sizeof(axMix[1]));
	axMix[1].vR = 0x7FFF;
	
	AXSetVoiceMix(axVoice[0],&axMix[0]);
	AXSetVoiceMix(axVoice[1],&axMix[1]);
	
	axVE.currentDelta = 0;
	axVE.currentVolume = 0x7FFF;
	AXSetVoiceVe(axVoice[0],&axVE);
	AXSetVoiceVe(axVoice[1],&axVE);
	
	memset(&axSRC,0,sizeof(AXPBSRC));
	
	ratio = (u32)(65536.0f * (f32)audioPlayBufferFrq / (f32)AX_IN_SAMPLES_PER_SEC);
	axSRC.ratioHi = (u16)(ratio >> 16);
	axSRC.ratioLo = (u16)ratio;
	
	AXSetVoiceSrcType(axVoice[0],AX_SRC_TYPE_4TAP_16K);
	AXSetVoiceSrc(axVoice[0],&axSRC);
	AXSetVoiceSrcType(axVoice[1],AX_SRC_TYPE_4TAP_16K);
	AXSetVoiceSrc(axVoice[1],&axSRC);
	
	*(u32 *)&axAddr.currentAddressHi = AX_ARAM_LEFT_CHANNEL;
	*(u32 *)&axAddr.loopAddressHi = AX_ARAM_LEFT_CHANNEL;
	*(u32 *)&axAddr.endAddressHi = AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE - 1;
	axAddr.format = AX_PB_FORMAT_PCM16;
	axAddr.loopFlag = AXPBADDR_LOOP_ON;
	AXSetVoiceAddr(axVoice[0],&axAddr);
	
	*(u32 *)&axAddr.currentAddressHi = AX_ARAM_RIGHT_CHANNEL;
	*(u32 *)&axAddr.loopAddressHi = AX_ARAM_RIGHT_CHANNEL;
	*(u32 *)&axAddr.endAddressHi = AX_ARAM_RIGHT_CHANNEL + AX_ARAM_BUFFER_SIZE - 1;
	AXSetVoiceAddr(axVoice[1],&axAddr);

	memset(&axADPCM,0,sizeof(axADPCM));
	axADPCM.gain = 0x0800;
	
	AXSetVoiceAdpcm(axVoice[0],&axADPCM);
	AXSetVoiceAdpcm(axVoice[1],&axADPCM);
	
	AXSetVoiceType(axVoice[0],AX_PB_TYPE_STREAM);
	AXSetVoiceType(axVoice[1],AX_PB_TYPE_STREAM);
	
	AXRegisterCallback( AXCallback );
	
	axLastAddr				= AX_ARAM_LEFT_CHANNEL;
	axPlayedSamples			= AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS;
	axPlayedSamplesTotal	= 0;
	axPhase					= AX_PHASE_STARTUP;
	
	// All is setup for the voices. We'll start them inside the AX callback as soon as we got data in the ARAM buffers
	OSRestoreInterrupts(old);

	return TRUE;
    }
コード例 #7
0
ファイル: AUDSimplePlayer.cpp プロジェクト: basecq/thug
/*!
 ******************************************************************************
 * \brief
 *		Decode all frame data
 *
 *		This function operates on the full frame input data. It forwards this
 *		data to the required decoder.
 *
 ******************************************************************************
 */
BOOL AUDSimpleDecode(void)
{
	BOOL enabled;
	u8* chunkStart;
	u32 chunkSize;
	u32 frameSize;

	if( audio_player.readBuffer[audio_player.decodeIndex].valid )
	{
		
		// ptr to our (pre-) loaded data INSIDE (!) 'FRAM' chunk
		// (in other words, the 'FRAM' chunk itself is not visible here)
		chunkStart = audio_player.readBuffer[audio_player.decodeIndex].ptr;

		// usually, we read additional 32 bytes for getting info about the NEXT chunk.
		// We only deal with the actual 'FRAM' chunk data here and adjust the size by 32 bytes.
        frameSize = audio_player.readBuffer[audio_player.decodeIndex].size - 32;
		
		// loop across ALL chunks inside 'FRAM'
		while(frameSize >= 32)
		{
			chunkSize = VID_CHUNK_LEN(chunkStart);
			
			if( VID_CHUNK_ID(chunkStart) == VID_FCC('A','U','D','D') )
			{
				// Get the data to the audio system...
				if(! AUDSimpleAudioDecode(chunkStart + VID_CHUNK_HEADER_SIZE, chunkSize - VID_CHUNK_HEADER_SIZE))
				{
#ifdef _DEBUG
					OSReport("*** AUDSimpleAudioDecode failed!\n");
#endif
				}
			}
#ifdef _DEBUG
			else
			{
				OSReport("*** AUDSimpleDecode: unknown chunk type!\n");
			}
#endif
			
			// goto next chunk
			chunkStart += chunkSize;
			frameSize -= chunkSize;
		}
			
		audio_player.lastDecodedFrame = audio_player.readBuffer[audio_player.decodeIndex].frameNumber;
		audio_player.readBuffer[audio_player.decodeIndex].valid = FALSE;
		audio_player.decodeIndex = (audio_player.decodeIndex + 1) % AUD_NUM_READ_BUFFERS;

		// check if loading is still running
		enabled = OSDisableInterrupts();
		if (!audio_player.readBuffer[audio_player.readIndex].valid && !audio_player.asyncDvdRunning)
			ReadFrameAsync();
		OSRestoreInterrupts(enabled);
		
        return TRUE;
	}

#ifdef _DEBUG
	OSReport("*** AUDSimpleDecode: No valid decode buffer found (?).\n");
#endif
	return FALSE;

}