static int wav_get_bitrate (void *prv_data) { struct wavpack_data *data = (struct wavpack_data *)prv_data; int bitrate; bitrate = WavpackGetInstantBitrate (data->wpc) / 1000; return (bitrate == 0)? data->avg_bitrate : bitrate; }
EmErrorCode WvDecoder::DecodeUnit(char* data, uint32_t& used, uint32_t& unitCount) { if (m_UnitIndex < m_UnitCount) { unitCount = 1; // according to wavpack's source code cli/wvunpack.c uint32_t nsamples = WavpackUnpackSamples(m_Ctx, (int32_t*)&m_Buf[0], unitCount*m_Channels); format_samples(m_BytesPerSample, (unsigned char*)data, &m_Buf[0], nsamples*m_Channels); used = nsamples * m_BytesPerSample * m_Channels; m_UnitIndex += unitCount; m_BitRate = WavpackGetInstantBitrate(m_Ctx)/1000; return ErrorCode::Ok; } used = 0; unitCount = m_UnitCount; m_BitRate = 0; return ErrorCode::DecoderOutOfRange; }
/* * 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 int wv_read (DB_fileinfo_t *_info, char *bytes, int size) { wvctx_t *info = (wvctx_t *)_info; int currentsample = WavpackGetSampleIndex (info->ctx); int samplesize = _info->fmt.channels * _info->fmt.bps / 8; if (size / samplesize + currentsample > info->endsample) { size = (info->endsample - currentsample + 1) * samplesize; trace ("wv: size truncated to %d bytes (%d samples), cursample=%d, endsample=%d\n", size, info->endsample - currentsample + 1, currentsample, info->endsample); if (size <= 0) { return 0; } } int initsize = size; int n; if (WavpackGetMode (info->ctx) & MODE_FLOAT) { _info->fmt.is_float = 1; } if (_info->fmt.is_float || _info->fmt.bps == 32) { n = WavpackUnpackSamples (info->ctx, (int32_t *)bytes, size / samplesize); size -= n * samplesize; } else { int32_t buffer[size/(_info->fmt.bps / 8)]; n = WavpackUnpackSamples (info->ctx, (int32_t *)buffer, size / samplesize); size -= n * samplesize; n *= _info->fmt.channels; // convert from int32 to input (what???) int32_t *p = buffer; if (_info->fmt.bps == 16) { while (n > 0) { *((int16_t *)bytes) = (int16_t)(*p); bytes += sizeof (int16_t); p++; n--; } } else if (_info->fmt.bps == 8) { while (n > 0) { *bytes++ = (char)(*p); p++; n--; } } else if (_info->fmt.bps == 24) { while (n > 0) { *bytes++ = (*p)&0xff; *bytes++ = ((*p)&0xff00)>>8; *bytes++ = ((*p)&0xff0000)>>16; p++; n--; } } } _info->readpos = (float)(WavpackGetSampleIndex (info->ctx)-info->startsample)/WavpackGetSampleRate (info->ctx); #ifndef TINYWV deadbeef->streamer_set_bitrate (WavpackGetInstantBitrate (info->ctx) / 1000); #endif return initsize-size; }
/* * 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); } }