void Copy_set(void* ctx,int val) { SetHelp("Copy loop to clipboard"); audioCopy(); }
/*! ****************************************************************************** * \brief * AX callback * ****************************************************************************** */ static void AXCallback(void) { // First thing to do here is call the regular soundfx callback. Sfx::AXUserCBack(); u32 availSamples,availFrames,numUpdate,i,n; u32 audioPlayBufferNeededAudioFrames; u32 currentAddr; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (axPhase == AX_PHASE_START) { AXSetVoiceState(axVoice[0],AX_PB_STATE_RUN); AXSetVoiceState(axVoice[1],AX_PB_STATE_RUN); axPhase = AX_PHASE_PLAY; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - currentAddr = *(u32 *)&axVoice[0]->pb.addr.currentAddressHi; if( currentAddr >= axLastAddr ) { axPlayedSamples += currentAddr - axLastAddr; axPlayedSamplesTotal += currentAddr - axLastAddr; } else { axPlayedSamples += (( AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE ) - axLastAddr ) + ( currentAddr - AX_ARAM_LEFT_CHANNEL ); axPlayedSamplesTotal += (( AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE ) - axLastAddr ) + ( currentAddr - AX_ARAM_LEFT_CHANNEL ); } axLastAddr = currentAddr; // If we have played the required number of samples, stop the voice. if( axPlayedSamplesTotal >= audio_player.audioInfo.vaudex.totalSampleCount ) { AXSetVoiceState( axVoice[0], AX_PB_STATE_STOP ); AXSetVoiceState( axVoice[1], AX_PB_STATE_STOP ); audio_player.playbackComplete = true; return; } if( axPlayedSamples >= AUD_AUDIO_AIBUFFERSAMPLES ) { audioPlayBufferNeededAudioFrames = axPlayedSamples / AUD_AUDIO_AIBUFFERSAMPLES; // Make sure that we never get an underrun we don't notice... if( !( audioPlayBufferNeededAudioFrames <= AUD_AUDIO_NUMAIBUFFERS )) { // OSReport( "AX audio buffer underrun!\n" ); // Disable playback. audioPlayBufferEnabled = false; } // Is actual audio playback enabled? if( audioPlayBufferEnabled ) { // How many samples could we get from the read buffer? if( audioReadBufferWritePos >= audioReadBufferReadPos ) availSamples = audioReadBufferWritePos - audioReadBufferReadPos; else availSamples = audioReadBufferNumSamples - ( audioReadBufferReadPos - audioReadBufferWritePos ); // That's how many audio frames? availFrames = availSamples / AUD_AUDIO_AIBUFFERSAMPLES; //OSReport("AX: %d %d (%d)\n",availSamples,audioPlayBufferNeededAudioFrames * VID_AUDIO_AIBUFFERSAMPLES,axPlayedSamples); // So, how many can we update? numUpdate = ( availFrames > audioPlayBufferNeededAudioFrames ) ? audioPlayBufferNeededAudioFrames : availFrames; // If anything... go do it! if( numUpdate != 0 ) { axPlayedSamples -= numUpdate * AUD_AUDIO_AIBUFFERSAMPLES; // Perform updates on each AI buffer in need of data... for( i = 0; i < numUpdate; i++ ) { u32 leftSource, rightSource, leftTarget, rightTarget; // Can we copy everything from a single source or does the data wrap around? if(( n = audioReadBufferNumSamples - audioReadBufferReadPos) < AUD_AUDIO_AIBUFFERSAMPLES ) { // It wraps... audioCopy( 0, n ); audioCopy( n, AUD_AUDIO_AIBUFFERSAMPLES - n ); } else { // We got one continous source buffer audioCopy( 0, AUD_AUDIO_AIBUFFERSAMPLES ); } // Make sure the data ends up in real physical memory DCFlushRange( audioPlayBuffer[audioPlayBufferWriteIndex], AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ) * 2 ); leftSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex]; rightSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex] + ( AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 )); leftTarget = 2 * ( AX_ARAM_LEFT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES ); rightTarget = 2 * ( AX_ARAM_RIGHT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES ); // Make sure we get this into ARAM ASAP... ARQPostRequest( &arqRequest[0][i%AUD_NUM_ARQ_REQUESTS], 0, ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH, leftSource, leftTarget, AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ), NULL ); ARQPostRequest( &arqRequest[1][i%AUD_NUM_ARQ_REQUESTS], 1, ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH, rightSource, rightTarget, AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ), NULL ); // Advance write index... audioPlayBufferWriteIndex = (u8)(( audioPlayBufferWriteIndex + 1 ) % AUD_AUDIO_NUMAIBUFFERS ); } if( axPhase == AX_PHASE_STARTUP ) { axPhase = AX_PHASE_START; } } } else { // Update buffer(s) with silence... axPlayedSamples -= audioPlayBufferNeededAudioFrames * AUD_AUDIO_AIBUFFERSAMPLES; for( i = 0; i < audioPlayBufferNeededAudioFrames; i++ ) { u32 leftSource, rightSource, leftTarget, rightTarget; memset(audioPlayBuffer[audioPlayBufferWriteIndex],0,2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES); DCFlushRange(audioPlayBuffer[audioPlayBufferWriteIndex],2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES); leftSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex]; rightSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex] + (AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16)) / 2; leftTarget = 2 * (AX_ARAM_LEFT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES); rightTarget = 2 * (AX_ARAM_RIGHT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES); // Make sure we get this into ARAM ASAP... ARQPostRequest(&arqRequest[0][i%AUD_NUM_ARQ_REQUESTS],0,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,leftSource,leftTarget,AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL); ARQPostRequest(&arqRequest[1][i%AUD_NUM_ARQ_REQUESTS],1,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,rightSource,rightTarget,AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL); audioPlayBufferWriteIndex = (u8)((audioPlayBufferWriteIndex + 1) % AUD_AUDIO_NUMAIBUFFERS); } if (axPhase == AX_PHASE_STARTUP) axPhase = AX_PHASE_START; } } }