From 1093601a6e359de55d25721d14ee6885d672d4e4 Mon Sep 17 00:00:00 2001 From: David Griffith Date: Sun, 30 Aug 2015 17:44:01 -0700 Subject: [PATCH] Going back to calling libvorbisfile directly because libsndfile doesn't support reading OGGV embedded in other files. OGGV playback sort of works (slow and distorted). Turning it off isn't exactly right. --- src/curses/ux_audio.c | 152 ++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 96 deletions(-) diff --git a/src/curses/ux_audio.c b/src/curses/ux_audio.c index f8b505a..f9315c5 100644 --- a/src/curses/ux_audio.c +++ b/src/curses/ux_audio.c @@ -67,6 +67,7 @@ static void *playaiff(EFFECT *); static void *playmusic(EFFECT *); static void *playmod(EFFECT *); static void *playogg(EFFECT *); + static void floattopcm16(short *, float *, int); static void pcm16tofloat(float *, short *, int); static void stereoize(float *, float *, size_t); @@ -590,18 +591,15 @@ static void *playmusic(EFFECT *raw_effect) sem_post(&playmusic_okay); - if (myeffect.type == MOD) { - playmod(&myeffect); - printf(" mod done\n\r"); - } else if (myeffect.type == OGGV) { - playogg(&myeffect); - printf(" ogg done\n\r"); - } else; + if (myeffect.type == MOD) playmod(&myeffect); + else if (myeffect.type == OGGV) playogg(&myeffect); + else; pthread_exit(NULL); } /* playmusic */ + /* * playmod * @@ -721,128 +719,90 @@ static char *getfiledata(FILE *fp, long *size) * sure that an OGG chunk is to be played. Volume and repeats are also * handled here. * - * This function invoked libvorbisfile directly rather than going - * through libsndfile. The reason for this is that libsndfile refuses - * to load an OGG file that's embedded in a Blorb file. + * Libsndfile is capable of reading OGG files, but not if the file is + * embedded in another file. That's why we're using libvorbisfile + * directly instead of going through libsndfile. Erikd, main developer + * of libsndfile is working on a fix. * */ -void *playogg(EFFECT *raw_effect) +static void *playogg(EFFECT *raw_effect) { - long filestart; + ogg_int64_t toread; + ogg_int64_t frames_read; + ogg_int64_t count; - int volcount; - int volfactor; + vorbis_info *info; + + OggVorbis_File vf; + int current_section; + short *shortbuffer; float *floatbuffer; float *floatbuffer2; - SNDFILE *sndfile; - SF_INFO sf_info; - - SRC_STATE *src_state; - SRC_DATA src_data; - int error; - sf_count_t output_count = 0; + long filestart; + int volcount; + int volfactor; EFFECT myeffect = *raw_effect; - sf_info.format = 0; - musicnum = myeffect.number; + fseek(myeffect.fp, myeffect.result.data.startpos, SEEK_SET); - filestart = ftell(myeffect.fp); - lseek(fileno(myeffect.fp), myeffect.result.data.startpos, SEEK_SET); - sndfile = sf_open_fd(fileno(myeffect.fp), SFM_READ, &sf_info, 0); + if (ov_open_callbacks(myeffect.fp, &vf, NULL, 0, OV_CALLBACKS_NOCLOSE) < 0) { + printf("Unable to open OGGV stream.\n\r"); + return; + } + + info = ov_info(&vf, -1); + if (info == NULL) { + printf("Unable to get info on OGGV stream.\n\r"); + return; + } if (myeffect.vol < 1) myeffect.vol = 1; if (myeffect.vol > 8) myeffect.vol = 8; volfactor = mypower(2, -myeffect.vol + 8); - floatbuffer = malloc(BUFFSIZE * sf_info.channels * sizeof(float)); - floatbuffer2 = malloc(BUFFSIZE * 2 * sizeof(float)); - memset(bleepbuffer, 0, BUFFSIZE * sizeof(float) * 2); + shortbuffer = malloc(BUFFSIZE * info->channels * sizeof(short)); + floatbuffer = malloc(BUFFSIZE * info->channels * sizeof(float)); - /* Set up for conversion */ - if ((src_state = src_new(DEFAULT_CONVERTER, sf_info.channels, &error)) == NULL) { - printf("Error: src_new() failed: %s.\n", src_strerror(error)); - exit(1); - } - src_data.end_of_input = 0; - src_data.input_frames = 0; - src_data.data_in = floatbuffer; - src_data.src_ratio = (1.0 * SAMPLERATE) / sf_info.samplerate; - src_data.data_out = floatbuffer2; - src_data.output_frames = BUFFSIZE / sf_info.channels; + frames_read = 0; + toread = ov_pcm_total(&vf, -1) * 2 * info->channels; + count = 0; music_playing = TRUE; - while (1) { - /* Check if we're being told to stop. */ - if (!bleep_playing) break; + while (count < toread) { sem_wait(&audio_empty); pthread_mutex_lock(&mutex); + memset(musicbuffer, 0, BUFFSIZE * sizeof(float) * 2); + if (!music_playing) break; - /* If floatbuffer is empty, refill it. */ - if (src_data.input_frames == 0) { - src_data.input_frames = sf_readf_float(sndfile, floatbuffer, BUFFSIZE / sf_info.channels); - src_data.data_in = floatbuffer; - /* Mark end of input. */ - if (src_data.input_frames < BUFFSIZE / sf_info.channels) - src_data.end_of_input = SF_TRUE; - } - - /* Do the sample rate conversion. */ - if ((error = src_process(src_state, &src_data))) { - printf("Error: %s\n", src_strerror(error)); - exit(1); - } - - musicsamples = src_data.output_frames_gen * 2; - - /* Stereoize monaural sound-effects. */ - if (sf_info.channels == 1) { - /* Remember that each monaural frame contains just one sample. */ - stereoize(musicbuffer, floatbuffer2, src_data.output_frames_gen); - } else { - /* It's already stereo. Just copy the buffer. */ - memcpy(musicbuffer, floatbuffer2, sizeof(float) * src_data.output_frames_gen * 2); - } - - /* Adjust volume. */ - for (volcount = 0; volcount <= musicsamples; volcount++) - musicbuffer[volcount] /= volfactor; - - /* If that's all, terminate and signal that we're done. */ - if (src_data.end_of_input && src_data.output_frames_gen == 0) { - pthread_mutex_unlock(&mutex); - sem_post(&audio_full); - break; - } + frames_read = ov_read(&vf, (char *)shortbuffer, BUFFSIZE, 0,2,1,¤t_section); + pcm16tofloat(floatbuffer, shortbuffer, frames_read); + for (volcount = 0; volcount <= frames_read / 2; volcount++) { + ((float *) floatbuffer)[volcount] /= volfactor; + } - /* Get ready for the next chunk. */ - output_count += src_data.output_frames_gen; - src_data.data_in += src_data.input_frames_used * sf_info.channels; - src_data.input_frames -= src_data.input_frames_used; + musicsamples = frames_read; + memcpy(musicbuffer, floatbuffer, musicsamples); + count += frames_read; - /* By this time, the buffer is full. Signal the mixer to play it. */ pthread_mutex_unlock(&mutex); sem_post(&audio_full); } - - /* The two ways to exit the above loop are to process all the - * samples in the AIFF file or else get told to stop early. - * Whichever, we need to clean up and terminate this thread. - */ - music_playing = FALSE; + memset(musicbuffer, 0, BUFFSIZE * sizeof(float) * 2); + pthread_mutex_unlock(&mutex); -// sem_post(&audio_empty); + sem_post(&audio_empty); - fseek(myeffect.fp, filestart, SEEK_SET); - sf_close(sndfile); + ov_clear(&vf); + + free(shortbuffer); free(floatbuffer); - free(floatbuffer2); - pthread_exit(NULL); -} /* playmod */ + return; +} /* playogg */ #endif /* NO_SOUND */ -- 2.34.1