Exemplo n.º 1
0
static const struct audio_format *
ao_filter_open(struct audio_output *ao,
               struct audio_format *audio_format,
               GError **error_r)
{
    assert(audio_format_valid(audio_format));

    /* the replay_gain filter cannot fail here */
    if (ao->replay_gain_filter != NULL)
        filter_open(ao->replay_gain_filter, audio_format, error_r);
    if (ao->other_replay_gain_filter != NULL)
        filter_open(ao->other_replay_gain_filter, audio_format,
                    error_r);

    const struct audio_format *af
        = filter_open(ao->filter, audio_format, error_r);
    if (af == NULL) {
        if (ao->replay_gain_filter != NULL)
            filter_close(ao->replay_gain_filter);
        if (ao->other_replay_gain_filter != NULL)
            filter_close(ao->other_replay_gain_filter);
    }

    return af;
}
Exemplo n.º 2
0
void decoder_initialized(G_GNUC_UNUSED struct decoder * decoder,
			 const struct audio_format *audio_format,
			 bool seekable, float total_time)
{
	assert(dc.state == DECODE_STATE_START);
	assert(decoder != NULL);
	assert(decoder->stream_tag == NULL);
	assert(decoder->decoder_tag == NULL);
	assert(!decoder->seeking);
	assert(audio_format != NULL);
	assert(audio_format_defined(audio_format));
	assert(audio_format_valid(audio_format));

	dc.in_audio_format = *audio_format;
	getOutputAudioFormat(audio_format, &dc.out_audio_format);

	dc.seekable = seekable;
	dc.total_time = total_time;

	dc.state = DECODE_STATE_DECODE;
	notify_signal(&pc.notify);

	g_debug("audio_format=%u:%u:%u, seekable=%s",
		dc.in_audio_format.sample_rate, dc.in_audio_format.bits,
		dc.in_audio_format.channels,
		seekable ? "true" : "false");

	if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format))
		g_debug("converting to %u:%u:%u",
			dc.out_audio_format.sample_rate,
			dc.out_audio_format.bits,
			dc.out_audio_format.channels);
}
Exemplo n.º 3
0
bool
audio_format_parse(struct audio_format *dest, const char *src,
		   bool mask, GError **error_r)
{
	uint32_t rate;
	enum sample_format sample_format;
	uint8_t channels;

	audio_format_clear(dest);

	/* parse sample rate */

#if GCC_CHECK_VERSION(4,7)
	/* workaround -Wmaybe-uninitialized false positive */
	rate = 0;
#endif

	if (!parse_sample_rate(src, mask, &rate, &src, error_r))
		return false;

	if (*src++ != ':') {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Sample format missing");
		return false;
	}

	/* parse sample format */

#if GCC_CHECK_VERSION(4,7)
	/* workaround -Wmaybe-uninitialized false positive */
	sample_format = SAMPLE_FORMAT_UNDEFINED;
#endif

	if (!parse_sample_format(src, mask, &sample_format, &src, error_r))
		return false;

	if (*src++ != ':') {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Channel count missing");
		return false;
	}

	/* parse channel count */

	if (!parse_channel_count(src, mask, &channels, &src, error_r))
		return false;

	if (*src != 0) {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Extra data after channel count: %s", src);
		return false;
	}

	audio_format_init(dest, rate, sample_format, channels);
	assert(mask ? audio_format_mask_valid(dest)
	       : audio_format_valid(dest));

	return true;
}
Exemplo n.º 4
0
void
audio_format_mask_apply(struct audio_format *af,
                        const struct audio_format *mask)
{
    assert(audio_format_valid(af));
    assert(audio_format_mask_valid(mask));

    if (mask->sample_rate != 0)
        af->sample_rate = mask->sample_rate;

    if (mask->format != SAMPLE_FORMAT_UNDEFINED)
        af->format = mask->format;

    if (mask->channels != 0)
        af->channels = mask->channels;

    assert(audio_format_valid(af));
}
static const struct audio_format *
autoconvert_filter_open(struct filter *_filter,
			struct audio_format *in_audio_format,
			GError **error_r)
{
	struct autoconvert_filter *filter =
		(struct autoconvert_filter *)_filter;
	const struct audio_format *out_audio_format;

	assert(audio_format_valid(in_audio_format));

	/* open the "real" filter */

	filter->in_audio_format = *in_audio_format;

	out_audio_format = filter_open(filter->filter,
				       &filter->in_audio_format, error_r);
	if (out_audio_format == NULL)
		return NULL;

	/* need to convert? */

	if (!audio_format_equals(&filter->in_audio_format, in_audio_format)) {
		/* yes - create a convert_filter */
		struct audio_format audio_format2 = *in_audio_format;
		const struct audio_format *audio_format3;

		filter->convert = filter_new(&convert_filter_plugin, NULL,
					     error_r);
		if (filter->convert == NULL) {
			filter_close(filter->filter);
			return NULL;
		}

		audio_format3 = filter_open(filter->convert, &audio_format2,
					    error_r);
		if (audio_format3 == NULL) {
			filter_free(filter->convert);
			filter_close(filter->filter);
			return NULL;
		}

		assert(audio_format_equals(&audio_format2, in_audio_format));

		convert_filter_set(filter->convert, &filter->in_audio_format);
	} else
		/* no */
		filter->convert = NULL;

	return out_audio_format;
}
Exemplo n.º 6
0
static bool
wave_encoder_open(struct encoder *_encoder,
		  G_GNUC_UNUSED struct audio_format *audio_format,
		  G_GNUC_UNUSED GError **error)
{
	struct wave_encoder *encoder = (struct wave_encoder *)_encoder;

	assert(audio_format_valid(audio_format));

	switch (audio_format->format) {
	case SAMPLE_FORMAT_S8:
		encoder->bits = 8;
		break;

	case SAMPLE_FORMAT_S16:
		encoder->bits = 16;
		break;

	case SAMPLE_FORMAT_S24:
		audio_format->format = SAMPLE_FORMAT_S24_P32;
		encoder->bits = 24;
		break;

	case SAMPLE_FORMAT_S24_P32:
		encoder->bits = 24;
		break;

	case SAMPLE_FORMAT_S32:
		encoder->bits = 32;
		break;

	default:
		audio_format->format = SAMPLE_FORMAT_S16;
		encoder->bits = 16;
		break;
	}

	encoder->buffer = growing_fifo_new();
	struct wave_header *header =
		growing_fifo_write(&encoder->buffer, sizeof(*header));

	/* create PCM wave header in initial buffer */
	fill_wave_header(header,
			audio_format->channels,
			 encoder->bits,
			audio_format->sample_rate,
			 (encoder->bits / 8) * audio_format->channels );
	fifo_buffer_append(encoder->buffer, sizeof(*header));

	return true;
}
Exemplo n.º 7
0
bool
audio_format_init_checked(struct audio_format *af, unsigned long sample_rate,
			  enum sample_format sample_format, unsigned channels,
			  GError **error_r)
{
	if (audio_check_sample_rate(sample_rate, error_r) &&
	    audio_check_sample_format(sample_format, error_r) &&
	    audio_check_channel_count(channels, error_r)) {
		audio_format_init(af, sample_rate, sample_format, channels);
		assert(audio_format_valid(af));
		return true;
	} else
		return false;
}
Exemplo n.º 8
0
bool
audio_format_parse(struct audio_format *dest, const char *src,
		   bool mask, GError **error_r)
{
	uint32_t rate;
	enum sample_format sample_format;
	uint8_t channels;

	audio_format_clear(dest);

	/* parse sample rate */

	if (!parse_sample_rate(src, mask, &rate, &src, error_r))
		return false;

	if (*src++ != ':') {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Sample format missing");
		return false;
	}

	/* parse sample format */

	if (!parse_sample_format(src, mask, &sample_format, &src, error_r))
		return false;

	if (*src++ != ':') {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Channel count missing");
		return false;
	}

	/* parse channel count */

	if (!parse_channel_count(src, mask, &channels, &src, error_r))
		return false;

	if (*src != 0) {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Extra data after channel count: %s", src);
		return false;
	}

	audio_format_init(dest, rate, sample_format, channels);
	assert(mask ? audio_format_mask_valid(dest)
	       : audio_format_valid(dest));

	return true;
}
Exemplo n.º 9
0
void
decoder_initialized(struct decoder *decoder,
		    const struct audio_format *audio_format,
		    G_GNUC_UNUSED bool seekable,
		    G_GNUC_UNUSED float total_time)
{
	struct audio_format_string af_string;

	assert(!decoder->initialized);
	assert(audio_format_valid(audio_format));

	g_printerr("audio_format=%s\n",
		   audio_format_to_string(audio_format, &af_string));

	decoder->initialized = true;
}
Exemplo n.º 10
0
static bool
wave_encoder_open(struct encoder *_encoder,
		  G_GNUC_UNUSED struct audio_format *audio_format,
		  G_GNUC_UNUSED GError **error)
{
	struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
	void *buffer;

	assert(audio_format_valid(audio_format));

	switch (audio_format->format) {
	case SAMPLE_FORMAT_S8:
		encoder->bits = 8;
		break;

	case SAMPLE_FORMAT_S16:
		encoder->bits = 16;
		break;

	case SAMPLE_FORMAT_S24_P32:
		encoder->bits = 24;
		break;

	case SAMPLE_FORMAT_S32:
		encoder->bits = 32;
		break;

	default:
		audio_format->format = SAMPLE_FORMAT_S16;
		encoder->bits = 16;
		break;
	}

	buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) );

	/* create PCM wave header in initial buffer */
	fill_wave_header((struct wave_header *) buffer, 
			audio_format->channels,
			 encoder->bits,
			audio_format->sample_rate,
			 (encoder->bits / 8) * audio_format->channels );

	encoder->buffer_length = sizeof(struct wave_header);
	return true;
}
Exemplo n.º 11
0
unsigned cross_fade_calc(float duration, float total_time,
			 float mixramp_db, float mixramp_delay,
			 float replay_gain_db, float replay_gain_prev_db,
			 char *mixramp_start, char *mixramp_prev_end,
			 const struct audio_format *af,
			 const struct audio_format *old_format,
			 unsigned max_chunks)
{
	unsigned int chunks = 0;
	float chunks_f;
	float mixramp_overlap;

	if (duration < 0 || duration >= total_time ||
	    /* we can't crossfade when the audio formats are different */
	    !audio_format_equals(af, old_format))
		return 0;

	assert(duration >= 0);
	assert(audio_format_valid(af));

	chunks_f = (float)audio_format_time_to_size(af) / (float)CHUNK_SIZE;

	if (isnan(mixramp_delay) || !(mixramp_start) || !(mixramp_prev_end)) {
		chunks = (chunks_f * duration + 0.5);
	} else {
		/* Calculate mixramp overlap. */
		mixramp_overlap = mixramp_interpolate(mixramp_start, mixramp_db - replay_gain_db)
		  + mixramp_interpolate(mixramp_prev_end, mixramp_db - replay_gain_prev_db);
		if (!isnan(mixramp_overlap) && (mixramp_delay <= mixramp_overlap)) {
			chunks = (chunks_f * (mixramp_overlap - mixramp_delay));
			g_debug("will overlap %d chunks, %fs", chunks,
				mixramp_overlap - mixramp_delay);
		}
	}

	if (chunks > max_chunks) {
		chunks = max_chunks;
		g_warning("audio_buffer_size too small for computed MixRamp overlap");
	}

	return chunks;
}
Exemplo n.º 12
0
void
decoder_initialized(struct decoder *decoder,
		    const struct audio_format *audio_format,
		    bool seekable, float total_time)
{
	struct decoder_control *dc = decoder->dc;
	struct audio_format_string af_string;

	assert(dc->state == DECODE_STATE_START);
	assert(dc->pipe != NULL);
	assert(decoder != NULL);
	assert(decoder->stream_tag == NULL);
	assert(decoder->decoder_tag == NULL);
	assert(!decoder->seeking);
	assert(audio_format != NULL);
	assert(audio_format_defined(audio_format));
	assert(audio_format_valid(audio_format));

	dc->in_audio_format = *audio_format;
	getOutputAudioFormat(audio_format, &dc->out_audio_format);

	dc->seekable = seekable;
	dc->total_time = total_time;

	decoder_lock(dc);
	dc->state = DECODE_STATE_DECODE;
	decoder_unlock(dc);

	player_lock_signal();

	g_debug("audio_format=%s, seekable=%s",
		audio_format_to_string(&dc->in_audio_format, &af_string),
		seekable ? "true" : "false");

	if (!audio_format_equals(&dc->in_audio_format,
				 &dc->out_audio_format))
		g_debug("converting to %s",
			audio_format_to_string(&dc->out_audio_format,
					       &af_string));
}
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);
}
Exemplo n.º 14
0
/**
 * Object must be locked (and unlocked) by the caller.
 */
static bool
audio_output_open(struct audio_output *ao,
                  const struct audio_format *audio_format,
                  const struct music_pipe *mp)
{
    bool open;

    assert(ao != NULL);
    assert(ao->allow_play);
    assert(audio_format_valid(audio_format));
    assert(mp != NULL);

    if (ao->fail_timer != NULL) {
        g_timer_destroy(ao->fail_timer);
        ao->fail_timer = NULL;
    }

    if (ao->open &&
            audio_format_equals(audio_format, &ao->in_audio_format)) {
        assert(ao->pipe == mp ||
               (ao->always_on && ao->pause));

        if (ao->pause) {
            ao->chunk = NULL;
            ao->pipe = mp;

            /* unpause with the CANCEL command; this is a
               hack, but suits well for forcing the thread
               to leave the ao_pause() thread, and we need
               to flush the device buffer anyway */

            /* we're not using audio_output_cancel() here,
               because that function is asynchronous */
            ao_command(ao, AO_COMMAND_CANCEL);
        }

        return true;
    }

    ao->in_audio_format = *audio_format;
    ao->chunk = NULL;

    ao->pipe = mp;

    if (ao->thread == NULL)
        audio_output_thread_start(ao);

    ao_command(ao, ao->open ? AO_COMMAND_REOPEN : AO_COMMAND_OPEN);
    open = ao->open;

    if (open && ao->mixer != NULL) {
        GError *error = NULL;

        if (!mixer_open(ao->mixer, &error)) {
            g_warning("Failed to open mixer for '%s': %s",
                      ao->name, error->message);
            g_error_free(error);
        }
    }

    return open;
}
Exemplo n.º 15
0
static void
ao_open(struct audio_output *ao)
{
    bool success;
    GError *error = NULL;
    const struct audio_format *filter_audio_format;
    struct audio_format_string af_string;

    assert(!ao->open);
    assert(ao->pipe != NULL);
    assert(ao->chunk == NULL);
    assert(audio_format_valid(&ao->in_audio_format));

    if (ao->fail_timer != NULL) {
        /* this can only happen when this
           output thread fails while
           audio_output_open() is run in the
           player thread */
        g_timer_destroy(ao->fail_timer);
        ao->fail_timer = NULL;
    }

    /* enable the device (just in case the last enable has failed) */

    if (!ao_enable(ao))
        /* still no luck */
        return;

    /* open the filter */

    filter_audio_format = ao_filter_open(ao, &ao->in_audio_format, &error);
    if (filter_audio_format == NULL) {
        g_warning("Failed to open filter for \"%s\" [%s]: %s",
                  ao->name, ao->plugin->name, error->message);
        g_error_free(error);

        ao->fail_timer = g_timer_new();
        return;
    }

    assert(audio_format_valid(filter_audio_format));

    ao->out_audio_format = *filter_audio_format;
    audio_format_mask_apply(&ao->out_audio_format,
                            &ao->config_audio_format);

    g_mutex_unlock(ao->mutex);
    success = ao_plugin_open(ao->plugin, ao->data,
                             &ao->out_audio_format,
                             &error);
    g_mutex_lock(ao->mutex);

    assert(!ao->open);

    if (!success) {
        g_warning("Failed to open \"%s\" [%s]: %s",
                  ao->name, ao->plugin->name, error->message);
        g_error_free(error);

        ao_filter_close(ao);
        ao->fail_timer = g_timer_new();
        return;
    }

    convert_filter_set(ao->convert_filter, &ao->out_audio_format);

    ao->open = true;

    g_debug("opened plugin=%s name=\"%s\" "
            "audio_format=%s",
            ao->plugin->name, ao->name,
            audio_format_to_string(&ao->out_audio_format, &af_string));

    if (!audio_format_equals(&ao->in_audio_format,
                             &ao->out_audio_format))
        g_debug("converting from %s",
                audio_format_to_string(&ao->in_audio_format,
                                       &af_string));
}
Exemplo n.º 16
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);
}
Exemplo n.º 17
0
/*
 * 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);
}