signed int ReGBA_AudioUpdate() { u32 i, j; s16* audio_buff; s16 *dst_ptr, *dst_ptr1; u32 n = ds2_checkAudiobuff(); int ret; u8 WasInUnderrun = Stats.InSoundBufferUnderrun; Stats.InSoundBufferUnderrun = n == 0 && ReGBA_GetAudioSamplesAvailable() < AUDIO_LEN * 2; if (Stats.InSoundBufferUnderrun && !WasInUnderrun) Stats.SoundBufferUnderrunCount++; // On auto frameskip, sound buffers being full or empty determines // whether we're late. if (AUTO_SKIP) { if (n >= 2) { // We're in no hurry, because 2 buffers are still full. // Minimum skip 1 if(SKIP_RATE > 1) { #if defined TRACE || defined TRACE_FRAMESKIP ReGBA_Trace("I: Decreasing automatic frameskip: %u..%u", SKIP_RATE, SKIP_RATE - 1); #endif SKIP_RATE--; } } else { // Maximum skip 9 if(SKIP_RATE < 8) { #if defined TRACE || defined TRACE_FRAMESKIP ReGBA_Trace("I: Increasing automatic frameskip: %u..%u", SKIP_RATE, SKIP_RATE + 1); #endif SKIP_RATE++; } } } /* There must be AUDIO_LEN * 2 samples generated in order for the first * AUDIO_LEN to be valid. Some sound is generated in the past from the * future, and if the first AUDIO_LEN is grabbed before the core has had * time to generate all of it (at AUDIO_LEN * 2), the end may still be * silence, causing crackling. */ if (ReGBA_GetAudioSamplesAvailable() < AUDIO_LEN * 2) { // Generate more sound first, please! return -1; } // We have enough sound. Complete this update. if (game_fast_forward || temporary_fast_forward) { if (n >= AUDIO_BUFFER_COUNT) { // Drain the buffer down to a manageable size, then exit. // This needs to be high to avoid audible crackling/bubbling, // but not so high as to require all of the sound to be emitted. // gpSP synchronises on the sound, after all. -Neb, 2013-03-23 ReGBA_DiscardAudioSamples(ReGBA_GetAudioSamplesAvailable() - AUDIO_LEN); return 0; } } else { // Wait for at least one buffer to be free for audio. // Output assertion: The return value is between 0, inclusive, // and AUDIO_BUFFER_COUNT, inclusive, but can also be // 4294967295; that's (unsigned int) -1. (DSTWO SPECIFIC HACK) unsigned int n2; while ((n2 = ds2_checkAudiobuff()) >= AUDIO_BUFFER_COUNT && (int) n2 >= 0); } audio_buff = ds2_getAudiobuff(); if (audio_buff == NULL) { #if defined TRACE || defined TRACE_SOUND ReGBA_Trace("Recovered from the lack of a buffer"); #endif return -1; } dst_ptr = audio_buff; // left (stereo) dst_ptr1 = dst_ptr + (int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR); // right (stereo) for(i= 0; i < AUDIO_LEN; i += OUTPUT_FREQUENCY_DIVISOR) { s16 Left = 0, Right = 0, LeftPart, RightPart; for (j = 0; j < OUTPUT_FREQUENCY_DIVISOR; j++) { ReGBA_LoadNextAudioSample(&LeftPart, &RightPart); if (LeftPart > 2047) LeftPart = 2047; else if (LeftPart < -2048) LeftPart = -2048; Left += LeftPart / OUTPUT_FREQUENCY_DIVISOR; if (RightPart > 2047) RightPart = 2047; else if (RightPart < -2048) RightPart = -2048; Right += RightPart / OUTPUT_FREQUENCY_DIVISOR; } *dst_ptr++ = Left << 4; *dst_ptr1++ = Right << 4; } if (game_fast_forward || temporary_fast_forward) { // Dampen the sound with the previous samples written // (or unitialised data if we just started the emulator) StartFastForwardedSound(audio_buff, &audio_buff[(int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR)]); // Store the end for the next time EndFastForwardedSound(&audio_buff[(int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR) - DAMPEN_SAMPLE_COUNT], &audio_buff[(int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR) * 2 - DAMPEN_SAMPLE_COUNT]); } Stats.InSoundBufferUnderrun = 0; ds2_updateAudio(); return 0; }
int doPlay(FILE *fp, int samples_per_trans) { int len; int m, n; void *audiobuf; unsigned int key; int flag; int vol; unsigned short *audio_buffer_addr; len = wave_BytePsample * samples_per_trans; audiobuf = (void*)malloc(len); if(NULL == audiobuf) return -1; do { audio_buffer_addr = (unsigned short*)ds2_getAudiobuff(); } while(NULL == audio_buffer_addr); vol = 127; flag = 1; while(flag) { n = fread(audiobuf, 1, len, fp); if(0 == n) break; m = (n + len -1)/len; m *= len; if(n < m) { memset((char*)((unsigned int)audiobuf + n), 0, m -n); } //assume 16-bit and stereo audio unsigned short *src; unsigned short *dst0; unsigned short *dst1; src = (unsigned short*)audiobuf; //the audio buffer's front part are left channel's data, behind ate right // channel's data, different as the wave file, it's data not interleaved dst0 = audio_buffer_addr; dst1 = audio_buffer_addr + samples_per_trans; n = 0; while(n++ < samples_per_trans) { *dst0++ = *src++; *dst1++ = *src++; } //ther are 4 audio buffers on the ds2sdk, we should not make it overflow while(ds2_checkAudiobuff() > 3) { //128 samples (channles * Bytes Per channel) can play 2.9ms @ 44.1KHz //mdelay((samples_per_trans/128)*2.9); mdelay(1); } ds2_updateAudio(); while(ds2_checkAudiobuff() > 1) { key = getKey(); switch(key) { //incread volume case KEY_UP: vol += 1; if(vol > 255) vol = 255; ds2_setVolume(vol); printf("volume: %d\n", vol); break; //decreade volume case KEY_DOWN: vol -= 1; if(vol < 0) vol = 0; ds2_setVolume(vol); printf("volume: %d\n", vol); break; //exit case KEY_B: flag = 0; break; } } do { audio_buffer_addr = (unsigned short*)ds2_getAudiobuff(); } while(NULL == audio_buffer_addr); } free(audiobuf); return 0; }