static bool_t wv_play (InputPlayback * playback, const char * filename, VFSFile * file, int start_time, int stop_time, bool_t pause) { if (file == NULL) return FALSE; int32_t *input = NULL; void *output = NULL; int sample_rate, num_channels, bits_per_sample; unsigned num_samples; WavpackContext *ctx = NULL; VFSFile *wvc_input = NULL; bool_t error = FALSE; if (! wv_attach (filename, file, & wvc_input, & ctx, NULL, OPEN_TAGS | OPEN_WVC)) { fprintf (stderr, "Error opening Wavpack file '%s'.", filename); error = TRUE; goto error_exit; } sample_rate = WavpackGetSampleRate(ctx); num_channels = WavpackGetNumChannels(ctx); bits_per_sample = WavpackGetBitsPerSample(ctx); num_samples = WavpackGetNumSamples(ctx); if (!playback->output->open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels)) { fprintf (stderr, "Error opening audio output."); error = TRUE; goto error_exit; } if (pause) playback->output->pause(TRUE); input = malloc(BUFFER_SIZE * num_channels * sizeof(uint32_t)); output = malloc(BUFFER_SIZE * num_channels * SAMPLE_SIZE(bits_per_sample)); if (input == NULL || output == NULL) goto error_exit; playback->set_gain_from_playlist(playback); pthread_mutex_lock (& mutex); playback->set_params(playback, (int) WavpackGetAverageBitrate(ctx, num_channels), sample_rate, num_channels); seek_value = (start_time > 0) ? start_time : -1; stop_flag = FALSE; playback->set_pb_ready(playback); pthread_mutex_unlock (& mutex); while (!stop_flag && (stop_time < 0 || playback->output->written_time () < stop_time)) { int ret; unsigned samples_left; /* Handle seek and pause requests */ pthread_mutex_lock (& mutex); if (seek_value >= 0) { playback->output->flush (seek_value); WavpackSeekSample (ctx, (int64_t) seek_value * sample_rate / 1000); seek_value = -1; } pthread_mutex_unlock (& mutex); /* Decode audio data */ samples_left = num_samples - WavpackGetSampleIndex(ctx); ret = WavpackUnpackSamples(ctx, input, BUFFER_SIZE); if (samples_left == 0) stop_flag = TRUE; else if (ret < 0) { fprintf (stderr, "Error decoding file.\n"); break; } else { /* Perform audio data conversion and output */ unsigned i; int32_t *rp = input; int8_t *wp = output; int16_t *wp2 = output; int32_t *wp4 = output; if (bits_per_sample == 8) { for (i = 0; i < ret * num_channels; i++, wp++, rp++) *wp = *rp & 0xff; } else if (bits_per_sample == 16) { for (i = 0; i < ret * num_channels; i++, wp2++, rp++) *wp2 = *rp & 0xffff; } else if (bits_per_sample == 24 || bits_per_sample == 32) { for (i = 0; i < ret * num_channels; i++, wp4++, rp++) *wp4 = *rp; } playback->output->write_audio(output, ret * num_channels * SAMPLE_SIZE(bits_per_sample)); } } error_exit: free(input); free(output); wv_deattach (wvc_input, ctx); stop_flag = TRUE; return ! error; }
static gboolean wv_play (InputPlayback * playback, const gchar * filename, VFSFile * file, gint start_time, gint stop_time, gboolean pause) { if (file == NULL) return FALSE; gint32 *input = NULL; void *output = NULL; gint sample_rate, num_channels, bits_per_sample; guint num_samples; WavpackContext *ctx = NULL; VFSFile *wvc_input = NULL; gboolean error = FALSE; if (! wv_attach (filename, file, & wvc_input, & ctx, NULL, OPEN_TAGS | OPEN_WVC)) { g_warning("Error opening Wavpack file '%s'.", filename); error = TRUE; goto error_exit; } sample_rate = WavpackGetSampleRate(ctx); num_channels = WavpackGetNumChannels(ctx); bits_per_sample = WavpackGetBitsPerSample(ctx); num_samples = WavpackGetNumSamples(ctx); if (!playback->output->open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels)) { g_warning("Error opening audio output."); error = TRUE; goto error_exit; } if (pause) playback->output->pause(TRUE); input = g_malloc(BUFFER_SIZE * num_channels * sizeof(guint32)); output = g_malloc(BUFFER_SIZE * num_channels * SAMPLE_SIZE(bits_per_sample)); if (input == NULL || output == NULL) goto error_exit; playback->set_gain_from_playlist(playback); g_mutex_lock(ctrl_mutex); playback->set_params(playback, (gint) WavpackGetAverageBitrate(ctx, num_channels), sample_rate, num_channels); seek_value = (start_time > 0) ? start_time : -1; stop_flag = FALSE; playback->set_pb_ready(playback); g_mutex_unlock(ctrl_mutex); while (!stop_flag && (stop_time < 0 || playback->output->written_time () < stop_time)) { gint ret; guint samples_left; /* Handle seek and pause requests */ g_mutex_lock(ctrl_mutex); if (seek_value >= 0) { playback->output->flush (seek_value); WavpackSeekSample (ctx, (gint64) seek_value * sample_rate / 1000); seek_value = -1; g_cond_signal(ctrl_cond); } g_mutex_unlock(ctrl_mutex); /* Decode audio data */ samples_left = num_samples - WavpackGetSampleIndex(ctx); ret = WavpackUnpackSamples(ctx, input, BUFFER_SIZE); if (samples_left == 0) stop_flag = TRUE; else if (ret < 0) { g_warning("Error decoding file.\n"); break; } else { /* Perform audio data conversion and output */ guint i; gint32 *rp = input; gint8 *wp = output; gint16 *wp2 = output; gint32 *wp4 = output; if (bits_per_sample == 8) { for (i = 0; i < ret * num_channels; i++, wp++, rp++) *wp = *rp & 0xff; } else if (bits_per_sample == 16) { for (i = 0; i < ret * num_channels; i++, wp2++, rp++) *wp2 = *rp & 0xffff; } else if (bits_per_sample == 24 || bits_per_sample == 32) { for (i = 0; i < ret * num_channels; i++, wp4++, rp++) *wp4 = *rp; } playback->output->write_audio(output, ret * num_channels * SAMPLE_SIZE(bits_per_sample)); } } /* Flush buffer */ g_mutex_lock(ctrl_mutex); while (!stop_flag && playback->output->buffer_playing()) g_usleep(20000); g_cond_signal(ctrl_cond); g_mutex_unlock(ctrl_mutex); error_exit: g_free(input); g_free(output); wv_deattach (wvc_input, ctx); stop_flag = TRUE; playback->output->close_audio(); return ! error; }