/* * Test reading of audio files. */ void test_audio_file() { START_TEST; char* filenames[] = {"data/mono_0:10.wav", "data/stereo_0:10.wav", "data/mono_0:10.mp3", "data/stereo_0:10.mp3", "data/mono_0:10.m4a", "data/stereo_0:10.m4a", "data/mono_0:10.opus", "data/stereo_0:10.opus"}; int i; for(i=0;i<G_N_ELEMENTS(filenames);i++){ WfDecoder f = {{0,}}; char* filename = find_wav(filenames[i]); if(!ad_open(&f, filename)) FAIL_TEST("file open: %s", filenames[i]); if(!g_str_has_suffix(filenames[i], ".opus")){ assert(f.info.sample_rate == 44100, "samplerate: %i (expected 44100)", f.info.sample_rate); }else{ assert(f.info.sample_rate == 48000, "samplerate: %i (expected 48000)", f.info.sample_rate); } int n = 8; int read_len = WF_PEAK_RATIO * n; int16_t data[f.info.channels][read_len]; WfBuf16 buf = { .buf = {data[0], data[1]}, .size = n * WF_PEAK_RATIO }; size_t readcount = 0; size_t total = 0; do { readcount = ad_read_short(&f, &buf); total += readcount; } while (readcount > 0); dbg(1, "diff=%zu", abs((int)total - (int)f.info.frames)); if(g_str_has_suffix(filenames[i], ".wav") || g_str_has_suffix(filenames[i], ".flac")){ assert(total == f.info.frames, "%s: incorrect number of frames read: %"PRIi64, filenames[i], f.info.frames); assert(!(total % 512) || !(total % 100), "%s: bad framecount: %zu", filenames[i], total); // test file sizes are always a round number }else{ // for some file types, f.info.frames is only an estimate assert(abs((int)total - (int)f.info.frames) < 2048, "%s: incorrect number of frames read: %"PRIi64, filenames[i], f.info.frames); } ad_close(&f); g_free(filename); }
bool wf_ff_peakgen(const char* infilename, const char* peak_filename) { WfDecoder f = {{0,}}; if(!ad_open(&f, infilename)) return false; SNDFILE* outfile; SF_INFO sfinfo = { .format = SF_FORMAT_WAV | SF_FORMAT_PCM_16, .channels = f.info.channels, .samplerate = f.info.sample_rate, }; gchar* basename = g_path_get_basename(peak_filename); gchar* tmp_path = g_build_filename("/tmp", basename, NULL); g_free(basename); if(!(outfile = sf_open(tmp_path, SFM_WRITE, &sfinfo))) { printf ("Not able to open output file %s.\n", tmp_path); puts(sf_strerror(NULL)); return false; } int total_frames_written = 0; WfPeakSample total[sfinfo.channels]; memset(total, 0, sizeof(WfPeakSample) * sfinfo.channels); int n = 8; int read_len = WF_PEAK_RATIO * n; float* sf_data = g_malloc(sizeof(float) * read_len); int16_t data[f.info.channels][read_len]; WfBuf16 buf = { .buf = { data[0], data[1] }, .size = n * WF_PEAK_RATIO }; int readcount; int total_readcount = 0; do { readcount = ad_read_short(&f, &buf); total_readcount += readcount; int remaining = readcount; WfPeakSample peak[sfinfo.channels]; int j = 0; for(; j<n; j++) { WfPeakSample w[sfinfo.channels]; memset(peak, 0, sizeof(WfPeakSample) * sfinfo.channels); int k; for (k = 0; k < MIN(remaining, WF_PEAK_RATIO); k+=sfinfo.channels) { int c; for(c=0; c<sfinfo.channels; c++) { int16_t val = buf.buf[c][WF_PEAK_RATIO * j + k]; peak[c] = (WfPeakSample) { MAX(peak[c].positive, val), MIN(peak[c].negative, MAX(val, -32767)), // TODO value of SHRT_MAX messes up the rendering - why? }; } }; remaining -= WF_PEAK_RATIO; int c; for(c=0; c<sfinfo.channels; c++) { w[c] = peak[c]; total[c] = (WfPeakSample) { MAX(total[c].positive, w[c].positive), MIN(total[c].negative, w[c].negative), }; } total_frames_written += sf_writef_short (outfile, (short*)w, WF_PEAK_VALUES_PER_SAMPLE); } } while (readcount > 0); #if 0 if(f.info.channels > 1) dbg(0, "max=%i,%i min=%i,%i", total[0].positive, total[1].positive, total[0].negative, total[1].negative); else dbg(0, "max=%i min=%i", total[0].positive, total[0].negative); #endif #ifdef DEBUG if(g_str_has_suffix(infilename, ".mp3")) { dbg(1, "mp3"); f.info.frames = total_readcount; // update the estimate with the real frame count. } #else if(total_frames_written / WF_PEAK_VALUES_PER_SAMPLE != f.info.frames / WF_PEAK_RATIO) { gwarn("unexpected number of frames: %i != %Lu", total_frames_written / WF_PEAK_VALUES_PER_SAMPLE, f.info.frames / WF_PEAK_RATIO); } #endif ad_close(&f); sf_close (outfile); g_free(sf_data); int renamed = !rename(tmp_path, peak_filename); g_free(tmp_path); if(!renamed) return false; return true; }