int MYSTATICOGG::play_from(int position) { if (use_extra_sound_offset) extraOffset = ((16384 / (alogg_get_wave_is_stereo_ogg(tune) ? 2 : 1)) * 1000) / alogg_get_wave_freq_ogg(tune); else extraOffset = 0; if (alogg_play_ex_ogg(tune, 16384, vol, panning, 1000, repeat) != ALOGG_OK) { destroy(); delete this; return 0; } last_ms_offs = position; last_but_one = position; last_but_one_but_one = position; if (position > 0) alogg_seek_abs_msecs_ogg(tune, position); if (!psp_audio_multithreaded) poll(); return 1; }
SAMPLE * create_silence_sample(unsigned long ms) { SAMPLE * sp = NULL; int bits; int stereo; int freq; unsigned long samples, i; unsigned channels; eof_log("create_silence_sample() entered", 1); if(eof_music_track) { bits = alogg_get_wave_bits_ogg(eof_music_track); stereo = alogg_get_wave_is_stereo_ogg(eof_music_track); freq = alogg_get_wave_freq_ogg(eof_music_track); samples = msec_to_samples(ms); channels = stereo ? 2 : 1; } else { bits = 16; stereo = 1; freq = 44100; samples = (double)(ms * freq) / 1000.0; channels = 2; } sp = create_sample(bits, stereo, freq, samples); if(!sp) return NULL; //Return error if(bits == 8) { for(i = 0; i < samples * channels; i++) { ((unsigned char *)(sp->data))[i] = 0x80; } } else { for(i = 0; i < samples * channels; i++) { ((unsigned short *)(sp->data))[i] = 0x8000; } } return sp; }
int eof_add_silence_recode(char * oggfn, unsigned long ms) { char sys_command[1024] = {0}; char backupfn[1024] = {0}; char wavfn[1024] = {0}; char soggfn[1024] = {0}; ALOGG_OGG *oggfile = NULL; SAMPLE *decoded = NULL, *combined = NULL; int bits; int stereo; int freq; unsigned long samples; int channels; unsigned long ctr,index; void * oggbuffer = NULL; int bitrate; eof_log("eof_add_silence_recode() entered", 1); if(!oggfn || (ms == 0) || eof_silence_loaded) { return 41; //Return failure: Invalid parameters } set_window_title("Adjusting Silence..."); /* back up original file */ (void) snprintf(backupfn, sizeof(backupfn) - 1, "%s.backup", oggfn); if(!exists(backupfn)) { (void) eof_copy_file(oggfn, backupfn); } /* Decode the OGG file into memory */ //Load OGG file into memory oggbuffer = eof_buffer_file(oggfn, 0); //Decode the OGG from buffer instead of from file because the latter cannot support special characters in the file path due to limitations with fopen() if(!oggbuffer) { (void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tError reading OGG: \"%s\"", strerror(errno)); //Get the Operating System's reason for the failure eof_log(eof_log_string, 1); return 42; //Return failure: Could not buffer chart audio into memory } oggfile=alogg_create_ogg_from_buffer(oggbuffer, (int)file_size_ex(oggfn)); if(oggfile == NULL) { eof_log("ALOGG failed to open input audio file", 1); free(oggbuffer); return 43; //Return failure: Could not process buffered chart audio } //Decode OGG into memory decoded=alogg_create_sample_from_ogg(oggfile); if(decoded == NULL) { alogg_destroy_ogg(oggfile); free(oggbuffer); return 44; //Return failure: Could not decode chart audio to memory } /* Create a SAMPLE array large enough for the leading silence and the decoded OGG */ bits = alogg_get_wave_bits_ogg(oggfile); stereo = alogg_get_wave_is_stereo_ogg(oggfile); freq = alogg_get_wave_freq_ogg(oggfile); alogg_destroy_ogg(oggfile); //This is no longer needed oggfile = NULL; samples = msec_to_samples(ms); channels = stereo ? 2 : 1; combined = create_sample(bits,stereo,freq,samples+decoded->len); //Create a sample array long enough for the silence and the OGG file if(combined == NULL) { destroy_sample(decoded); return 45; //Return failure: Could not create a sample array for the combined audio } /* Add the PCM data for the silence */ if(bits == 8) { //Create 8 bit PCM data for(ctr=0,index=0;ctr < samples * channels;ctr++) { ((unsigned char *)(combined->data))[index++] = 0x80; } } else { //Create 16 bit PCM data for(ctr=0,index=0;ctr < samples * channels;ctr++) { ((unsigned short *)(combined->data))[index++] = 0x8000; } } /* Add the decoded OGG PCM data*/ if(bits == 8) { //Copy 8 bit PCM data for(ctr=0;ctr < decoded->len * channels;ctr++) { ((unsigned char *)(combined->data))[index++] = ((unsigned char *)(decoded->data))[ctr]; } } else { //Copy 16 bit PCM data for(ctr=0;ctr < decoded->len * channels;ctr++) { ((unsigned short *)(combined->data))[index++] = ((unsigned short *)(decoded->data))[ctr]; } } /* encode the audio */ destroy_sample(decoded); //This is no longer needed free(oggbuffer); (void) replace_filename(wavfn, eof_song_path, "encode.wav", 1024); (void) save_wav(wavfn, combined); destroy_sample(combined); //This is no longer needed (void) replace_filename(soggfn, eof_song_path, "encode.ogg", 1024); bitrate = alogg_get_bitrate_ogg(eof_music_track) / 1000; if(!bitrate) { //A user found that in an audio file with a really high sample rate (ie. 96KHz), alogg_get_bitrate_ogg() may return zero instead of an expected value bitrate = 256; //In case this happens, use a bitrate of 256Kbps, which should be good enough for a very high quality file } #ifdef ALLEGRO_WINDOWS (void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc2 -o \"%s\" -b %d \"%s\"", soggfn, bitrate, wavfn); #else (void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc -o \"%s\" -b %d \"%s\"", soggfn, bitrate, wavfn); #endif (void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tCalling oggenc as follows: %s", sys_command); eof_log(eof_log_string, 1); if(eof_system(sys_command)) { //If oggenc failed, retry again by specifying a quality level (specifying bitrate can fail in some circumstances) eof_log("\t\toggenc failed. Retrying by specifying a quality level instead of a target bitrate", 1); #ifdef ALLEGRO_WINDOWS (void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc2 -o \"%s\" -q 9 \"%s\"", soggfn, wavfn); #else (void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc -o \"%s\" -q 9 \"%s\"", soggfn, wavfn); #endif (void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tCalling oggenc as follows: %s", sys_command); eof_log(eof_log_string, 1); if(eof_system(sys_command)) { //If oggenc failed again char tempfname[30] = {0}; char redirect[35] = {0}; if(eof_validate_temp_folder()) { //Ensure the correct working directory and presence of the temporary folder eof_log("\tCould not validate working directory and temp folder", 1); return 46; //Return failure: Could not validate cwd and temp folder } (void) snprintf(tempfname, sizeof(tempfname) - 1, "%soggenc.log", eof_temp_path_s); (void) snprintf(redirect, sizeof(redirect) - 1, " 2> %s", tempfname); (void) ustrzcat(sys_command, (int) sizeof(sys_command) - 1, redirect); //Append a redirection to the command to capture the output of oggenc if(eof_system(sys_command)) { //Run one last time to catch the error output (void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tOggenc failed. Please see %s for any errors it gave.", tempfname); eof_log(eof_log_string, 1); eof_fix_window_title(); return 47; //Return failure: Could not encode combined audio } } } /* replace the current OGG file with the new file */ (void) eof_copy_file(soggfn, oggfn); //Copy encode.ogg to the filename of the original OGG /* clean up */ (void) delete_file(soggfn); //Delete encode.ogg (void) delete_file(wavfn); //Delete encode.wav if(eof_load_ogg(oggfn, 0)) { //If the combined audio was loaded eof_fix_waveform_graph(); eof_fix_spectrogram(); eof_fix_window_title(); eof_chart_length = eof_music_length; return 0; //Return success } eof_fix_window_title(); return 48; //Return error: Could not load new audio }
struct wavestruct *eof_create_waveform(char *oggfilename, unsigned long slicelength) { ALOGG_OGG *oggstruct = NULL; SAMPLE *audio = NULL; void * oggbuffer = NULL; struct wavestruct *waveform = NULL; static struct wavestruct emptywaveform; //all variables in this auto initialize to value 0 char done = 0; //-1 on unsuccessful completion, 1 on successful completion unsigned long slicenum = 0; eof_log("\tGenerating waveform", 1); eof_log("eof_create_waveform() entered", 1); set_window_title("Generating Waveform Graph..."); if((oggfilename == NULL) || !slicelength) { eof_log("Waveform: Invalid parameters", 1); return NULL; } //Load OGG file into memory oggbuffer = eof_buffer_file(oggfilename, 0); if(!oggbuffer) { (void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "Waveform: Failed to open input audio file: %s",strerror(errno)); eof_log(eof_log_string, 1); return NULL; } oggstruct = alogg_create_ogg_from_buffer(oggbuffer, (int)file_size_ex(oggfilename)); if(oggstruct == NULL) { eof_log("Waveform: ALOGG failed to open input audio file", 1); free(oggbuffer); return NULL; } //Decode OGG into memory audio = alogg_create_sample_from_ogg(oggstruct); if(audio == NULL) { eof_log("Waveform: ALOGG failed to decode input audio file", 1); done = -1; } else if((audio->bits != 8) && (audio->bits != 16)) //This logic currently only supports 8 and 16 bit audio { eof_log("Waveform: Invalid sample size", 1); done = -1; } else { //Initialize waveform structure waveform = (struct wavestruct *)malloc(sizeof(struct wavestruct)); if(waveform == NULL) { eof_log("Waveform: Unable to allocate memory for the waveform structure", 1); done = -1; } else { *waveform = emptywaveform; //Set all variables to value zero waveform->slicelength = slicelength; if(alogg_get_wave_is_stereo_ogg(oggstruct)) //If this audio file has two audio channels waveform->is_stereo = 1; else waveform->is_stereo = 0; if(audio->bits == 8) waveform->zeroamp = 128; //128 represents amplitude 0 for unsigned 8 bit audio samples else waveform->zeroamp = 32768; //32768 represents amplitude 0 for unsigned 16 bit audio samples waveform->oggfilename = (char *)malloc(strlen(oggfilename)+1); if(waveform->oggfilename == NULL) { eof_log("Waveform: Unable to allocate memory for the audio filename string", 1); done = -1; } else { waveform->slicesize = audio->freq * slicelength / 1000; //Find the number of samples in each slice if((audio->freq * slicelength) % 1000) //If there was any remainder waveform->slicesize++; //Increment the size of the slice waveform->numslices = (double)audio->len / ((double)audio->freq * (double)slicelength / 1000.0); //Find the number of slices to process if(audio->len % waveform->numslices) //If there's any remainder waveform->numslices++; //Increment the number of slices strcpy(waveform->oggfilename,oggfilename); waveform->left.slices = (struct waveformslice *)malloc(sizeof(struct waveformslice) * waveform->numslices); if(waveform->left.slices == NULL) { eof_log("Waveform: Unable to allocate memory for the left channel waveform data", 1); done = -1; } else if(waveform->is_stereo) //If this OGG is stereo { //Allocate memory for the right channel waveform data waveform->right.slices = (struct waveformslice *)malloc(sizeof(struct waveformslice) * waveform->numslices); if(waveform->right.slices == NULL) { eof_log("Waveform: Unable to allocate memory for the right channel waveform data", 1); done = -1; } } } } } while(!done) { done = eof_process_next_waveform_slice(waveform, audio, slicenum++); } //Cleanup if(oggstruct != NULL) alogg_destroy_ogg(oggstruct); if(audio != NULL) destroy_sample(audio); if(oggbuffer) free(oggbuffer); if(done == -1) //Unsuccessful completion { if(waveform) { if(waveform->oggfilename) free(waveform->oggfilename); free(waveform); } allegro_message("Failed to generate waveform. See log for details"); return NULL; //Return error } //Cache the difference between each channel's zero amplitude and its maximum amplitude for optimized rendering if(waveform->left.maxamp > waveform->zeroamp) waveform->left.maxampoffset = waveform->left.maxamp - waveform->zeroamp; else waveform->left.maxampoffset = waveform->zeroamp - waveform->left.maxamp; if(waveform->is_stereo) { //If there is right channel waveform data if(waveform->right.maxamp > waveform->zeroamp) waveform->right.maxampoffset = waveform->right.maxamp - waveform->zeroamp; else waveform->right.maxampoffset = waveform->zeroamp - waveform->right.maxamp; } eof_log("\tWaveform generated", 1); return waveform; //Return waveform data }
void eof_mix_start_helper(void) { int i; eof_log("eof_mix_start_helper() entered", 1); eof_mix_find_claps(); eof_mix_current_clap = -1; eof_mix_next_clap = -1; for(i = 0; i < eof_mix_claps; i++) { if(eof_mix_clap_pos[i] >= eof_mix_sample_count) { eof_mix_current_clap = i; eof_mix_next_clap = eof_mix_clap_pos[i]; break; } } eof_mix_current_metronome = -1; eof_mix_next_metronome = -1; for(i = 0; i < eof_mix_metronomes; i++) { if(eof_mix_metronome_pos[i] >= eof_mix_sample_count) { eof_mix_current_metronome = i; eof_mix_next_metronome = eof_mix_metronome_pos[i]; break; } } eof_mix_current_note = -1; eof_mix_next_note = -1; for(i = 0; i < eof_mix_notes; i++) { if(eof_mix_note_pos[i] >= eof_mix_sample_count) { eof_mix_current_note = i; eof_mix_next_note = eof_mix_note_pos[i]; break; } } eof_mix_current_percussion = -1; eof_mix_next_percussion = -1; for(i = 0; i < eof_mix_percussions; i++) { if(eof_mix_percussion_pos[i] >= eof_mix_sample_count) { eof_mix_current_percussion = i; eof_mix_next_percussion = eof_mix_percussion_pos[i]; break; } } eof_mix_current_guitar_note = -1; eof_mix_next_guitar_note = -1; for(i = 0; i < eof_mix_guitar_notes; i++) { if(eof_guitar_notes[i].pos >= eof_mix_sample_count) { eof_mix_current_guitar_note = i; eof_mix_next_guitar_note = eof_guitar_notes[i].pos; break; } } if(eof_disable_sound_processing) { //If callback processing is disabled alogg_set_buffer_callback(NULL); //Alogg will not invoke a callback if it is NULL } else if(alogg_get_wave_is_stereo_ogg(eof_music_track)) { //If the chart audio is in stereo, use the stereo callback function alogg_set_buffer_callback(eof_mix_callback_stereo); } else { //Otherwise use the mono callback function alogg_set_buffer_callback(eof_mix_callback_mono); } }