FskErr androidAudioOutGetSamplePosition(FskAudioOut audioOut, FskSampleTime *position) { androidAudioExt *ext = (androidAudioExt*)audioOut->ext; FskInt64 add; FskErr err = kFskErrNone; SLresult res; UInt32 pos; FskMutexAcquire(ext->getSamplePositionMutex); *position = audioOut->zeroTime; if (audioOut->playing) { SLmillisecond msec; res = (*ext->playItf)->GetPosition(ext->playItf, &msec); CheckErr(" audioOutGetSamplePosition", res); add = MSToSamples(audioOut, msec); pos = (UInt32)add; FskAudioNativePrintfVerbose("GetSamplePosition returns msec: %d, pos: %d", msec, pos); } else { add = ext->stoppedAtSamplePosition; } add -= ext->startedAtSamplePosition; *position += add; FskAudioNativePrintfVerbose("getSamplePosition %d - %d ms -- start@ %d, last stop@ %d, zero@ %lld", (UInt32)*position, (*position * 1000) / audioOut->sampleRate , (UInt32)ext->startedAtSamplePosition, (UInt32)ext->stoppedAtSamplePosition, audioOut->zeroTime); releaseAndBail: FskMutexRelease(ext->getSamplePositionMutex); return err; }
static bool init_buffers(void) { int i; // free the old buffers, as we're probably going to change their size here in a sec free_buffers(); /* figure some stuff out real quick about buffer lengths --- */ // convert the ms-per-beat stuff into samples song.samples_per_beat = MSToSamples(song.ms_per_beat); song.note_closing_samples = MSToSamples(song.ms_of_last_beat_of_note); // take the suggestion on cache ahead time (which is in ms) and figure out how many beats that is buffer_beats = (cache_ahead_time / song.ms_per_beat) + 1; if (buffer_beats < 3) buffer_beats = 3; // now figure out how many samples that is. buffer_samples = (buffer_beats * song.samples_per_beat); // now figure out how many bytes THAT is. outbuffer_size_bytes = buffer_samples * 2 * 2; // @ 16-bits, and stereo sound // initilize the per-channel output buffers for(i=0;i<16;i++) { note_channel[i].outbuffer = (signed short *)malloc(outbuffer_size_bytes); note_channel[i].number = i; //memset(note_channel[i].outbuffer, 0, outbuffer_size_bytes); } // initilize the final (mixed) output buffers for(i=0;i<2;i++) { final_buffer[i].samples = (signed short *)malloc(outbuffer_size_bytes); //memset(final_buffer[i].samples, 0, outbuffer_size_bytes); } return 0; }
FskErr androidAudioOutStart(FskAudioOut audioOut, FskSampleTime atSample) { FskErr err = kFskErrNone; androidAudioExt *ext = (androidAudioExt*)audioOut->ext; SLresult res; FskAudioNativePrintfVerbose("audioOutStart %x - atSample %lld", audioOut, atSample); if (audioOut->playing) goto bail; if (!ext->playItf) { FskAudioNativePrintfMinimal("huh? No playItf"); err = kFskErrOperationFailed; goto bail; } audioOut->zeroTime = atSample; ext->stoppedAtSamplePosition = 0; FskTimeCallbackNew(&ext->flushTimer); FskTimeCallbackScheduleFuture(ext->flushTimer, 0, kFlushAndRefillTime, flushNowCallback, audioOut); FskAudioNativePrintfVerbose("androidAudioOutStart %x - zeroTime %d", audioOut, audioOut->zeroTime); // in case volume has changed when audio was off // androidAudioOutSetVolume(audioOut, audioOut->leftVolume, audioOut->rightVolume); refillQueue(audioOut); fillBuffers(audioOut); audioOut->playing = true; // refillQueue(audioOut); FskTimeGetNow(&ext->lastTime); FskMutexAcquire(gActiveAudioMutex); gActiveAudioOut = audioOut; FskMutexRelease(gActiveAudioMutex); res = (*ext->playItf)->SetPlayState(ext->playItf, SL_PLAYSTATE_PLAYING); CheckErr(" audioOutStart - set playstate playing", res); { SLmillisecond msec; res = (*ext->playItf)->GetPosition(ext->playItf, &msec); CheckErr(" androidAudioOutStart", res); ext->startedAtSamplePosition = MSToSamples(audioOut, msec); } bail: return err; }
void pmd_start(void) { song.beat = 0; song.samples = 0; song.samples_per_beat = MSToSamples(song.ms_per_beat); song.samples_left_in_beat = 0; running_notes.MakeEmpty(); queue_and_start_buffer(0); queue_and_start_buffer(1); buffer_needed = false; curbuffer = 0; stat("Starting pmd playback: %d ms per beat, %d samples per beat", \ song.ms_per_beat, song.samples_per_beat); pmd_set_volume(PMD_NORMAL_VOLUME); song.playing = true; }