static void sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) { GError *error = NULL; SNDFILE *sf; SF_INFO info; struct audio_format audio_format; size_t frame_size; sf_count_t read_frames, num_frames; int buffer[4096]; enum decoder_command cmd; info.format = 0; sf = sf_open_virtual(&vio, SFM_READ, &info, is); if (sf == NULL) { g_warning("sf_open_virtual() failed"); return; } /* for now, always read 32 bit samples. Later, we could lower MPD's CPU usage by reading 16 bit samples with sf_readf_short() on low-quality source files. */ if (!audio_format_init_checked(&audio_format, info.samplerate, SAMPLE_FORMAT_S32, info.channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } decoder_initialized(decoder, &audio_format, info.seekable, frame_to_time(info.frames, &audio_format)); frame_size = audio_format_frame_size(&audio_format); read_frames = sizeof(buffer) / frame_size; do { num_frames = sf_readf_int(sf, buffer, read_frames); if (num_frames <= 0) break; cmd = decoder_data(decoder, is, buffer, num_frames * frame_size, 0); if (cmd == DECODE_COMMAND_SEEK) { sf_count_t c = time_to_frame(decoder_seek_where(decoder), &audio_format); c = sf_seek(sf, c, SEEK_SET); if (c < 0) decoder_seek_error(decoder); else decoder_command_finished(decoder); cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); sf_close(sf); }
/** * Decode one "DSD" chunk. */ static bool dsdiff_decode_chunk(struct decoder *decoder, struct input_stream *is, unsigned channels, uint64_t chunk_size, bool fileisdff, bool bitreverse) { uint8_t buffer[8192]; /* Scratch buffer for DSF samples to convert to the needed normal Left/Right regime of samples */ uint8_t dsf_scratch_buffer[8192]; const size_t sample_size = sizeof(buffer[0]); const size_t frame_size = channels * sample_size; const unsigned buffer_frames = sizeof(buffer) / frame_size; const unsigned buffer_samples = buffer_frames * frame_size; const size_t buffer_size = buffer_samples * sample_size; while (chunk_size > 0) { /* see how much aligned data from the remaining chunk fits into the local buffer */ unsigned now_frames = buffer_frames; size_t now_size = buffer_size; if (chunk_size < (uint64_t)now_size) { now_frames = (unsigned)chunk_size / frame_size; now_size = now_frames * frame_size; } size_t nbytes = decoder_read(decoder, is, buffer, now_size); if (nbytes != now_size) return false; chunk_size -= nbytes; if (lsbitfirst || bitreverse) bit_reverse_buffer(buffer, buffer + nbytes); if (!fileisdff) dsf_to_pcm_order(buffer, dsf_scratch_buffer, nbytes); enum decoder_command cmd = decoder_data(decoder, is, buffer, nbytes, 0); switch (cmd) { case DECODE_COMMAND_NONE: break; case DECODE_COMMAND_START: case DECODE_COMMAND_STOP: return false; case DECODE_COMMAND_SEEK: /* not implemented yet */ decoder_seek_error(decoder); break; } } return dsdiff_skip(decoder, is, chunk_size); }
/** * Sends the synthesized current frame via decoder_data(). */ static enum decoder_command mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length) { unsigned max_samples; max_samples = sizeof(data->output_buffer) / sizeof(data->output_buffer[0]) / MAD_NCHANNELS(&(data->frame).header); while (i < pcm_length) { enum decoder_command cmd; unsigned int num_samples = pcm_length - i; if (num_samples > max_samples) num_samples = max_samples; i += num_samples; mad_fixed_to_24_buffer(data->output_buffer, &data->synth, i - num_samples, i, MAD_NCHANNELS(&(data->frame).header)); num_samples *= MAD_NCHANNELS(&(data->frame).header); cmd = decoder_data(data->decoder, data->input_stream, data->output_buffer, sizeof(data->output_buffer[0]) * num_samples, data->bit_rate / 1000); if (cmd != DECODE_COMMAND_NONE) return cmd; } return DECODE_COMMAND_NONE; }
static void pcm_stream_decode(struct decoder *decoder, struct input_stream *is) { static const struct audio_format audio_format = { .sample_rate = 44100, .format = SAMPLE_FORMAT_S16, .channels = 2, }; GError *error = NULL; enum decoder_command cmd; double time_to_size = audio_format_time_to_size(&audio_format); float total_time = -1; if (is->size >= 0) total_time = is->size / time_to_size; decoder_initialized(decoder, &audio_format, is->seekable, total_time); do { char buffer[4096]; size_t nbytes = decoder_read(decoder, is, buffer, sizeof(buffer)); if (nbytes == 0 && input_stream_eof(is)) break; cmd = nbytes > 0 ? decoder_data(decoder, is, buffer, nbytes, 0) : decoder_get_command(decoder); if (cmd == DECODE_COMMAND_SEEK) { goffset offset = (goffset)(time_to_size * decoder_seek_where(decoder)); if (input_stream_seek(is, offset, SEEK_SET, &error)) { decoder_command_finished(decoder); } else { g_warning("seeking failed: %s", error->message); g_error_free(error); decoder_seek_error(decoder); } cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); } static const char *const pcm_mime_types[] = { /* for streams obtained by the cdio_paranoia input plugin */ "audio/x-mpd-cdda-pcm", NULL }; const struct decoder_plugin pcm_decoder_plugin = { .name = "pcm", .stream_decode = pcm_stream_decode, .mime_types = pcm_mime_types, };
FLAC__StreamDecoderWriteStatus flac_common_write(struct flac_data *data, const FLAC__Frame * frame, const FLAC__int32 *const buf[], FLAC__uint64 nbytes) { enum decoder_command cmd; void *buffer; unsigned bit_rate; if (!data->initialized && !flac_got_first_frame(data, &frame->header)) return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; size_t buffer_size = frame->header.blocksize * data->frame_size; buffer = pcm_buffer_get(&data->buffer, buffer_size); flac_convert(buffer, frame->header.channels, data->audio_format.format, buf, 0, frame->header.blocksize); if (nbytes > 0) bit_rate = nbytes * 8 * frame->header.sample_rate / (1000 * frame->header.blocksize); else bit_rate = 0; cmd = decoder_data(data->decoder, data->input_stream, buffer, buffer_size, bit_rate); data->next_frame += frame->header.blocksize; switch (cmd) { case DECODE_COMMAND_NONE: case DECODE_COMMAND_START: break; case DECODE_COMMAND_STOP: return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; case DECODE_COMMAND_SEEK: return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; }
/* public */ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { GError *error = NULL; OggVorbis_File vf; struct vorbis_input_stream vis; struct audio_format audio_format; float total_time; int current_section; int prev_section = -1; long ret; char chunk[OGG_CHUNK_SIZE]; long bitRate = 0; long test; const vorbis_info *vi; enum decoder_command cmd = DECODE_COMMAND_NONE; if (ogg_stream_type_detect(input_stream) != VORBIS) return; /* rewind the stream, because ogg_stream_type_detect() has moved it */ input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); if (!vorbis_is_open(&vis, &vf, decoder, input_stream)) return; vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); return; } if (!audio_format_init_checked(&audio_format, vi->rate, SAMPLE_FORMAT_S16, vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } total_time = ov_time_total(&vf, -1); if (total_time < 0) total_time = 0; decoder_initialized(decoder, &audio_format, vis.seekable, total_time); do { if (cmd == DECODE_COMMAND_SEEK) { double seek_where = decoder_seek_where(decoder); if (0 == ov_time_seek_page(&vf, seek_where)) { decoder_command_finished(decoder); } else decoder_seek_error(decoder); } ret = ov_read(&vf, chunk, sizeof(chunk), OGG_DECODE_USE_BIGENDIAN, 2, 1, ¤t_section); if (ret == OV_HOLE) /* bad packet */ ret = 0; else if (ret <= 0) /* break on EOF or other error */ break; if (current_section != prev_section) { char **comments; vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); break; } if (vi->rate != (long)audio_format.sample_rate || vi->channels != (int)audio_format.channels) { /* we don't support audio format change yet */ g_warning("audio format change, stopping here"); break; } comments = ov_comment(&vf, -1)->user_comments; vorbis_send_comments(decoder, input_stream, comments); struct replay_gain_info rgi; if (vorbis_comments_to_replay_gain(&rgi, comments)) decoder_replay_gain(decoder, &rgi); prev_section = current_section; } if ((test = ov_bitrate_instant(&vf)) > 0) bitRate = test / 1000; cmd = decoder_data(decoder, input_stream, chunk, ret, bitRate); } while (cmd != DECODE_COMMAND_STOP); ov_clear(&vf); }
static void wildmidi_file_decode(struct decoder *decoder, const char *path_fs) { static const struct audio_format audio_format = { .sample_rate = WILDMIDI_SAMPLE_RATE, .format = SAMPLE_FORMAT_S16, .channels = 2, }; midi *wm; const struct _WM_Info *info; enum decoder_command cmd; wm = WildMidi_Open(path_fs); if (wm == NULL) return; info = WildMidi_GetInfo(wm); if (info == NULL) { WildMidi_Close(wm); return; } decoder_initialized(decoder, &audio_format, true, info->approx_total_samples / WILDMIDI_SAMPLE_RATE); do { char buffer[4096]; int len; info = WildMidi_GetInfo(wm); if (info == NULL) break; len = WildMidi_GetOutput(wm, buffer, sizeof(buffer)); if (len <= 0) break; cmd = decoder_data(decoder, NULL, buffer, len, 0); if (cmd == DECODE_COMMAND_SEEK) { unsigned long seek_where = WILDMIDI_SAMPLE_RATE * decoder_seek_where(decoder); WildMidi_SampledSeek(wm, &seek_where); decoder_command_finished(decoder); cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); WildMidi_Close(wm); } static struct tag * wildmidi_tag_dup(const char *path_fs) { midi *wm; const struct _WM_Info *info; struct tag *tag; wm = WildMidi_Open(path_fs); if (wm == NULL) return NULL; info = WildMidi_GetInfo(wm); if (info == NULL) { WildMidi_Close(wm); return NULL; } tag = tag_new(); tag->time = info->approx_total_samples / WILDMIDI_SAMPLE_RATE; WildMidi_Close(wm); return tag; }
static void fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) { char setting_sample_rate[] = "synth.sample-rate"; /* char setting_verbose[] = "synth.verbose"; char setting_yes[] = "yes"; */ fluid_settings_t *settings; fluid_synth_t *synth; fluid_player_t *player; int ret; enum decoder_command cmd; /* set up fluid settings */ settings = new_fluid_settings(); if (settings == NULL) return; fluid_settings_setnum(settings, setting_sample_rate, sample_rate); /* fluid_settings_setstr(settings, setting_verbose, setting_yes); */ /* create the fluid synth */ synth = new_fluid_synth(settings); if (synth == NULL) { delete_fluid_settings(settings); return; } ret = fluid_synth_sfload(synth, soundfont_path, true); if (ret < 0) { g_warning("fluid_synth_sfload() failed"); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* create the fluid player */ player = new_fluid_player(synth); if (player == NULL) { delete_fluid_synth(synth); delete_fluid_settings(settings); return; } ret = fluid_player_add(player, path_fs); if (ret != 0) { g_warning("fluid_player_add() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* start the player */ ret = fluid_player_play(player); if (ret != 0) { g_warning("fluid_player_play() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* initialization complete - announce the audio format to the MPD core */ struct audio_format audio_format; audio_format_init(&audio_format, sample_rate, SAMPLE_FORMAT_S16, 2); decoder_initialized(decoder, &audio_format, false, -1); while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) { int16_t buffer[2048]; const unsigned max_frames = G_N_ELEMENTS(buffer) / 2; /* read samples from fluidsynth and send them to the MPD core */ ret = fluid_synth_write_s16(synth, max_frames, buffer, 0, 2, buffer, 1, 2); if (ret != 0) break; cmd = decoder_data(decoder, NULL, buffer, sizeof(buffer), 0); if (cmd != DECODE_COMMAND_NONE) break; } /* clean up */ fluid_player_stop(player); fluid_player_join(player); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); }
static void mod_decode(struct decoder *decoder, struct input_stream *is) { ModPlugFile *f; ModPlug_Settings settings; GByteArray *bdatas; struct audio_format audio_format; int ret; char audio_buffer[MODPLUG_FRAME_SIZE]; enum decoder_command cmd = DECODE_COMMAND_NONE; bdatas = mod_loadfile(decoder, is); if (!bdatas) { g_warning("could not load stream\n"); return; } ModPlug_GetSettings(&settings); /* alter setting */ settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */ settings.mChannels = 2; settings.mBits = 16; settings.mFrequency = 44100; /* insert more setting changes here */ ModPlug_SetSettings(&settings); f = ModPlug_Load(bdatas->data, bdatas->len); g_byte_array_free(bdatas, TRUE); if (!f) { g_warning("could not decode stream\n"); return; } audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); assert(audio_format_valid(&audio_format)); decoder_initialized(decoder, &audio_format, is->seekable, ModPlug_GetLength(f) / 1000.0); do { ret = ModPlug_Read(f, audio_buffer, MODPLUG_FRAME_SIZE); if (ret <= 0) break; cmd = decoder_data(decoder, NULL, audio_buffer, ret, 0); if (cmd == DECODE_COMMAND_SEEK) { float where = decoder_seek_where(decoder); ModPlug_Seek(f, (int)(where * 1000.0)); decoder_command_finished(decoder); } } while (cmd != DECODE_COMMAND_STOP); ModPlug_Unload(f); }
static void fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) { static const struct audio_format audio_format = { .sample_rate = 48000, .bits = 16, .channels = 2, }; char setting_sample_rate[] = "synth.sample-rate"; /* char setting_verbose[] = "synth.verbose"; char setting_yes[] = "yes"; */ const char *soundfont_path; fluid_settings_t *settings; fluid_synth_t *synth; fluid_player_t *player; char *path_dup; int ret; Timer *timer; enum decoder_command cmd; soundfont_path = config_get_string("soundfont", "/usr/share/sounds/sf2/FluidR3_GM.sf2"); /* set up fluid settings */ settings = new_fluid_settings(); if (settings == NULL) return; fluid_settings_setnum(settings, setting_sample_rate, 48000); /* fluid_settings_setstr(settings, setting_verbose, setting_yes); */ /* create the fluid synth */ synth = new_fluid_synth(settings); if (synth == NULL) { delete_fluid_settings(settings); return; } ret = fluid_synth_sfload(synth, soundfont_path, true); if (ret < 0) { g_warning("fluid_synth_sfload() failed"); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* create the fluid player */ player = new_fluid_player(synth); if (player == NULL) { delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* temporarily duplicate the path_fs string, because fluidsynth wants a writable string */ path_dup = g_strdup(path_fs); ret = fluid_player_add(player, path_dup); g_free(path_dup); if (ret != 0) { g_warning("fluid_player_add() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* start the player */ ret = fluid_player_play(player); if (ret != 0) { g_warning("fluid_player_play() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* set up a timer for synchronization; fluidsynth always decodes in real time, which forces us to synchronize */ /* XXX is there any way to switch off real-time decoding? */ timer = timer_new(&audio_format); timer_start(timer); /* initialization complete - announce the audio format to the MPD core */ decoder_initialized(decoder, &audio_format, false, -1); do { int16_t buffer[2048]; const unsigned max_frames = G_N_ELEMENTS(buffer) / 2; /* synchronize with the fluid player */ timer_add(timer, sizeof(buffer)); timer_sync(timer); /* read samples from fluidsynth and send them to the MPD core */ ret = fluid_synth_write_s16(synth, max_frames, buffer, 0, 2, buffer, 1, 2); /* XXX how do we see whether the player is done? We can't access the private attribute player->status */ if (ret != 0) break; cmd = decoder_data(decoder, NULL, buffer, sizeof(buffer), 0, 0, NULL); } while (cmd == DECODE_COMMAND_NONE); /* clean up */ timer_free(timer); fluid_player_stop(player); fluid_player_join(player); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); } static struct tag * fluidsynth_tag_dup(const char *file) { struct tag *tag = tag_new(); /* to be implemented */ (void)file; return tag; } static const char *const fluidsynth_suffixes[] = { "mid", NULL }; const struct decoder_plugin fluidsynth_decoder_plugin = { .name = "fluidsynth", .init = fluidsynth_init, .file_decode = fluidsynth_file_decode, .tag_dup = fluidsynth_tag_dup, .suffixes = fluidsynth_suffixes, };
/* * This does the main decoding thing. * Requires an already opened WavpackContext. */ static void wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, struct replay_gain_info *replay_gain_info) { struct audio_format audio_format; format_samples_t format_samples; char chunk[CHUNK_SIZE]; int samples_requested, samples_got; float total_time, current_time; int bytes_per_sample, output_sample_size; int position; audio_format.sample_rate = WavpackGetSampleRate(wpc); audio_format.channels = WavpackGetReducedChannels(wpc); audio_format.bits = WavpackGetBitsPerSample(wpc); /* round bitwidth to 8-bit units */ audio_format.bits = (audio_format.bits + 7) & (~7); /* mpd handles max 24-bit samples */ if (audio_format.bits > 24) { audio_format.bits = 24; } if (!audio_format_valid(&audio_format)) { g_warning("Invalid audio format: %u:%u:%u\n", audio_format.sample_rate, audio_format.bits, audio_format.channels); return; } if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) { format_samples = format_samples_float; } else { format_samples = format_samples_int; } total_time = WavpackGetNumSamples(wpc); total_time /= audio_format.sample_rate; bytes_per_sample = WavpackGetBytesPerSample(wpc); output_sample_size = audio_format_frame_size(&audio_format); /* wavpack gives us all kind of samples in a 32-bit space */ samples_requested = sizeof(chunk) / (4 * audio_format.channels); decoder_initialized(decoder, &audio_format, can_seek, total_time); position = 0; do { if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) { if (can_seek) { int where; where = decoder_seek_where(decoder); where *= audio_format.sample_rate; if (WavpackSeekSample(wpc, where)) { position = where; decoder_command_finished(decoder); } else { decoder_seek_error(decoder); } } else { decoder_seek_error(decoder); } } if (decoder_get_command(decoder) == DECODE_COMMAND_STOP) { break; } samples_got = WavpackUnpackSamples( wpc, (int32_t *)chunk, samples_requested ); if (samples_got > 0) { int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 + 0.5); position += samples_got; current_time = position; current_time /= audio_format.sample_rate; format_samples( bytes_per_sample, chunk, samples_got * audio_format.channels ); decoder_data( decoder, NULL, chunk, samples_got * output_sample_size, current_time, bitrate, replay_gain_info ); } } while (samples_got > 0); }
static void audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) { AFvirtualfile *vf; int fs, frame_count; AFfilehandle af_fp; int bits; struct audio_format audio_format; float total_time; uint16_t bit_rate; int ret, current = 0; char chunk[CHUNK_SIZE]; enum decoder_command cmd; if (!is->seekable) { g_warning("not seekable"); return; } vf = setup_virtual_fops(is); af_fp = afOpenVirtualFile(vf, "r", NULL); if (af_fp == AF_NULL_FILEHANDLE) { g_warning("failed to input stream\n"); return; } afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); if (!audio_valid_sample_format(bits)) { g_debug("input file has %d bit samples, converting to 16", bits); bits = 16; } afSetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, bits); afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); audio_format.bits = (uint8_t)bits; audio_format.sample_rate = (unsigned int)afGetRate(af_fp, AF_DEFAULT_TRACK); audio_format.channels = (uint8_t)afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK); if (!audio_format_valid(&audio_format)) { g_warning("Invalid audio format: %u:%u:%u\n", audio_format.sample_rate, audio_format.bits, audio_format.channels); afCloseFile(af_fp); return; } frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK); total_time = ((float)frame_count / (float)audio_format.sample_rate); bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5); fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); decoder_initialized(decoder, &audio_format, true, total_time); do { ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, CHUNK_SIZE / fs); if (ret <= 0) break; current += ret; cmd = decoder_data(decoder, NULL, chunk, ret * fs, (float)current / (float)audio_format.sample_rate, bit_rate, NULL); if (cmd == DECODE_COMMAND_SEEK) { current = decoder_seek_where(decoder) * audio_format.sample_rate; afSeekFrame(af_fp, AF_DEFAULT_TRACK, current); decoder_command_finished(decoder); cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); afCloseFile(af_fp); }
static void audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) { GError *error = NULL; AFvirtualfile *vf; int fs, frame_count; AFfilehandle af_fp; struct audio_format audio_format; float total_time; uint16_t bit_rate; int ret; char chunk[CHUNK_SIZE]; enum decoder_command cmd; if (!is->seekable) { g_warning("not seekable"); return; } vf = setup_virtual_fops(is); af_fp = afOpenVirtualFile(vf, "r", NULL); if (af_fp == AF_NULL_FILEHANDLE) { g_warning("failed to input stream\n"); return; } if (!audio_format_init_checked(&audio_format, afGetRate(af_fp, AF_DEFAULT_TRACK), audiofile_setup_sample_format(af_fp), afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK), &error)) { g_warning("%s", error->message); g_error_free(error); afCloseFile(af_fp); return; } frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK); total_time = ((float)frame_count / (float)audio_format.sample_rate); bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5); fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); decoder_initialized(decoder, &audio_format, true, total_time); do { ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, CHUNK_SIZE / fs); if (ret <= 0) break; cmd = decoder_data(decoder, NULL, chunk, ret * fs, bit_rate); if (cmd == DECODE_COMMAND_SEEK) { AFframecount frame = decoder_seek_where(decoder) * audio_format.sample_rate; afSeekFrame(af_fp, AF_DEFAULT_TRACK, frame); decoder_command_finished(decoder); cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); afCloseFile(af_fp); }
/* public */ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { GError *error = NULL; if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS) return; /* rewind the stream, because ogg_codec_detect() has moved it */ input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); struct vorbis_input_stream vis; OggVorbis_File vf; if (!vorbis_is_open(&vis, &vf, decoder, input_stream)) return; const vorbis_info *vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); return; } struct audio_format audio_format; if (!audio_format_init_checked(&audio_format, vi->rate, #ifdef HAVE_TREMOR SAMPLE_FORMAT_S16, #else SAMPLE_FORMAT_FLOAT, #endif vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } float total_time = ov_time_total(&vf, -1); if (total_time < 0) total_time = 0; decoder_initialized(decoder, &audio_format, vis.seekable, total_time); enum decoder_command cmd = decoder_get_command(decoder); #ifdef HAVE_TREMOR char buffer[4096]; #else float buffer[2048]; const int frames_per_buffer = G_N_ELEMENTS(buffer) / audio_format.channels; const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels; #endif int prev_section = -1; unsigned kbit_rate = 0; do { if (cmd == DECODE_COMMAND_SEEK) { double seek_where = decoder_seek_where(decoder); if (0 == ov_time_seek_page(&vf, seek_where)) { decoder_command_finished(decoder); } else decoder_seek_error(decoder); } int current_section; #ifdef HAVE_TREMOR long nbytes = ov_read(&vf, buffer, sizeof(buffer), VORBIS_BIG_ENDIAN, 2, 1, ¤t_section); #else float **per_channel; long nframes = ov_read_float(&vf, &per_channel, frames_per_buffer, ¤t_section); long nbytes = nframes; if (nframes > 0) { vorbis_interleave(buffer, (const float*const*)per_channel, nframes, audio_format.channels); nbytes *= frame_size; } #endif if (nbytes == OV_HOLE) /* bad packet */ nbytes = 0; else if (nbytes <= 0) /* break on EOF or other error */ break; if (current_section != prev_section) { vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); break; } if (vi->rate != (long)audio_format.sample_rate || vi->channels != (int)audio_format.channels) { /* we don't support audio format change yet */ g_warning("audio format change, stopping here"); break; } char **comments = ov_comment(&vf, -1)->user_comments; vorbis_send_comments(decoder, input_stream, comments); struct replay_gain_info rgi; if (vorbis_comments_to_replay_gain(&rgi, comments)) decoder_replay_gain(decoder, &rgi); prev_section = current_section; } long test = ov_bitrate_instant(&vf); if (test > 0) kbit_rate = test / 1000; cmd = decoder_data(decoder, input_stream, buffer, nbytes, kbit_rate); } while (cmd != DECODE_COMMAND_STOP); ov_clear(&vf); }
/* * This does the main decoding thing. * Requires an already opened WavpackContext. */ static void wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek) { GError *error = NULL; bool is_float; enum sample_format sample_format; struct audio_format audio_format; format_samples_t format_samples; float total_time; int bytes_per_sample, output_sample_size; is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0; sample_format = wavpack_bits_to_sample_format(is_float, WavpackGetBytesPerSample(wpc)); if (!audio_format_init_checked(&audio_format, WavpackGetSampleRate(wpc), sample_format, WavpackGetNumChannels(wpc), &error)) { g_warning("%s", error->message); g_error_free(error); return; } if (is_float) { format_samples = format_samples_float; } else { format_samples = format_samples_int; } total_time = WavpackGetNumSamples(wpc); total_time /= audio_format.sample_rate; bytes_per_sample = WavpackGetBytesPerSample(wpc); output_sample_size = audio_format_frame_size(&audio_format); /* wavpack gives us all kind of samples in a 32-bit space */ int32_t chunk[1024]; const uint32_t samples_requested = G_N_ELEMENTS(chunk) / audio_format.channels; decoder_initialized(decoder, &audio_format, can_seek, total_time); enum decoder_command cmd = decoder_get_command(decoder); while (cmd != DECODE_COMMAND_STOP) { if (cmd == DECODE_COMMAND_SEEK) { if (can_seek) { unsigned where = decoder_seek_where(decoder) * audio_format.sample_rate; if (WavpackSeekSample(wpc, where)) { decoder_command_finished(decoder); } else { decoder_seek_error(decoder); } } else { decoder_seek_error(decoder); } } uint32_t samples_got = WavpackUnpackSamples(wpc, chunk, samples_requested); if (samples_got == 0) break; int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 + 0.5); format_samples(bytes_per_sample, chunk, samples_got * audio_format.channels); cmd = decoder_data(decoder, NULL, chunk, samples_got * output_sample_size, bitrate); } }