Example #1
0
int
dsp_apply (ddb_waveformat_t *input_fmt, char *input, int inputsize,
           ddb_waveformat_t *out_fmt, char **out_bytes, int *out_numbytes, float *out_dsp_ratio) {

    *out_dsp_ratio = 1;

    ddb_waveformat_t dspfmt;
    memcpy (&dspfmt, input_fmt, sizeof (ddb_waveformat_t));
    dspfmt.bps = 32;
    dspfmt.is_float = 1;

    int can_bypass = 0;
    if (dsp_on) {
        // check if DSP can be passed through
        ddb_dsp_context_t *dsp = dsp_chain;
        while (dsp) {
            if (dsp->enabled) {
                if (dsp->plugin->plugin.api_vminor >= 1) {
                    if (dsp->plugin->can_bypass && !dsp->plugin->can_bypass (dsp, &dspfmt)) {
                        break;
                    }
                }
                else {
                    break;
                }
            }
            dsp = dsp->next;
        }
        if (!dsp) {
            can_bypass = 1;
        }
    }

    if (!dsp_on || can_bypass) {
        return 0;
    }

    int inputsamplesize = input_fmt->channels * input_fmt->bps / 8;

    // convert to float, pass through streamer DSP chain
    int dspsamplesize = input_fmt->channels * sizeof (float);

    // make *MAX_DSP_RATIO sized buffer for float data
    int tempbuf_size = inputsize/inputsamplesize * dspsamplesize * MAX_DSP_RATIO;
    char *tempbuf = ensure_dsp_temp_buffer (tempbuf_size);

    // convert to float
    /*int tempsize = */pcm_convert (input_fmt, input, &dspfmt, tempbuf, inputsize);
    int nframes = inputsize / inputsamplesize;
    ddb_dsp_context_t *dsp = dsp_chain;
    float ratio = 1.f;
    int maxframes = tempbuf_size / dspsamplesize;
    while (dsp) {
        if (dsp->enabled) {
            float r = 1;
            nframes = dsp->plugin->process (dsp, (float *)tempbuf, nframes, maxframes, &dspfmt, &r);
            ratio *= r;
        }
        dsp = dsp->next;
    }

    *out_dsp_ratio = ratio;

    memcpy (out_fmt, &dspfmt, sizeof (ddb_waveformat_t));
    *out_bytes = tempbuf;
    *out_numbytes = nframes * dspfmt.channels * sizeof (float);

    return 1;
}
Example #2
0
enum decoder_command
decoder_data(struct decoder *decoder,
	     struct input_stream *is,
	     const void *_data, size_t length,
	     uint16_t kbit_rate)
{
	struct decoder_control *dc = decoder->dc;
	const char *data = _data;
	GError *error = NULL;
	enum decoder_command cmd;

	assert(dc->state == DECODE_STATE_DECODE);
	assert(dc->pipe != NULL);
	assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);

	decoder_lock(dc);
	cmd = decoder_get_virtual_command(decoder);
	decoder_unlock(dc);

	if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
	    length == 0)
		return cmd;

	/* send stream tags */

	if (update_stream_tag(decoder, is)) {
		if (decoder->decoder_tag != NULL) {
			/* merge with tag from decoder plugin */
			struct tag *tag;

			tag = tag_merge(decoder->decoder_tag,
					decoder->stream_tag);
			cmd = do_send_tag(decoder, is, tag);
			tag_free(tag);
		} else
			/* send only the stream tag */
			cmd = do_send_tag(decoder, is, decoder->stream_tag);

		if (cmd != DECODE_COMMAND_NONE)
			return cmd;
	}

	if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
		data = pcm_convert(&decoder->conv_state,
				   &dc->in_audio_format, data, length,
				   &dc->out_audio_format, &length,
				   &error);
		if (data == NULL) {
			/* the PCM conversion has failed - stop
			   playback, since we have no better way to
			   bail out */
			g_warning("%s", error->message);
			return DECODE_COMMAND_STOP;
		}
	}

	while (length > 0) {
		struct music_chunk *chunk;
		char *dest;
		size_t nbytes;
		bool full;

		chunk = decoder_get_chunk(decoder, is);
		if (chunk == NULL) {
			assert(dc->command != DECODE_COMMAND_NONE);
			return dc->command;
		}

		dest = music_chunk_write(chunk, &dc->out_audio_format,
					 decoder->timestamp -
					 dc->song->start_ms / 1000.0,
					 kbit_rate, &nbytes);
		if (dest == NULL) {
			/* the chunk is full, flush it */
			decoder_flush_chunk(decoder);
			player_lock_signal();
			continue;
		}

		assert(nbytes > 0);

		if (nbytes > length)
			nbytes = length;

		/* copy the buffer */

		memcpy(dest, data, nbytes);

		/* expand the music pipe chunk */

		full = music_chunk_expand(chunk, &dc->out_audio_format, nbytes);
		if (full) {
			/* the chunk is full, flush it */
			decoder_flush_chunk(decoder);
			player_lock_signal();
		}

		data += nbytes;
		length -= nbytes;

		decoder->timestamp += (double)nbytes /
			audio_format_time_to_size(&dc->out_audio_format);

		if (dc->end_ms > 0 &&
		    decoder->timestamp >= dc->end_ms / 1000.0)
			/* the end of this range has been reached:
			   stop decoding */
			return DECODE_COMMAND_STOP;
	}

	return DECODE_COMMAND_NONE;
}
Example #3
0
enum decoder_command
decoder_data(struct decoder *decoder,
	     struct input_stream *is,
	     const void *_data, size_t length,
	     float data_time, uint16_t bitRate,
	     struct replay_gain_info *replay_gain_info)
{
	const char *data = _data;

	assert(dc.state == DECODE_STATE_DECODE);
	assert(length % audio_format_frame_size(&dc.in_audio_format) == 0);

	if (dc.command == DECODE_COMMAND_STOP ||
	    dc.command == DECODE_COMMAND_SEEK ||
	    length == 0)
		return dc.command;

	/* send stream tags */

	if (update_stream_tag(decoder, is)) {
		enum decoder_command cmd;

		if (decoder->decoder_tag != NULL) {
			/* merge with tag from decoder plugin */
			struct tag *tag;

			tag = tag_merge(decoder->stream_tag,
					decoder->decoder_tag);
			cmd = do_send_tag(decoder, is, tag);
			tag_free(tag);
		} else
			/* send only the stream tag */
			cmd = do_send_tag(decoder, is, decoder->stream_tag);

		if (cmd != DECODE_COMMAND_NONE)
			return cmd;
	}

	if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
		data = pcm_convert(&decoder->conv_state,
				   &dc.in_audio_format, data, length,
				   &dc.out_audio_format, &length);

		/* under certain circumstances, pcm_convert() may
		   return an empty buffer - this condition should be
		   investigated further, but for now, do this check as
		   a workaround: */
		if (data == NULL)
			return DECODE_COMMAND_NONE;
	}

	while (length > 0) {
		struct music_chunk *chunk;
		char *dest;
		size_t nbytes;
		bool full;

		chunk = decoder_get_chunk(decoder, is);
		if (chunk == NULL) {
			assert(dc.command != DECODE_COMMAND_NONE);
			return dc.command;
		}

		dest = music_chunk_write(chunk, &dc.out_audio_format,
					 data_time, bitRate, &nbytes);
		if (dest == NULL) {
			/* the chunk is full, flush it */
			decoder_flush_chunk(decoder);
			notify_signal(&pc.notify);
			continue;
		}

		assert(nbytes > 0);

		if (nbytes > length)
			nbytes = length;

		/* copy the buffer */

		memcpy(dest, data, nbytes);

		/* apply replay gain or normalization */

		if (replay_gain_info != NULL &&
		    replay_gain_mode != REPLAY_GAIN_OFF)
			replay_gain_apply(replay_gain_info, dest, nbytes,
					  &dc.out_audio_format);
		else if (normalizationEnabled)
			normalizeData(dest, nbytes, &dc.out_audio_format);

		/* expand the music pipe chunk */

		full = music_chunk_expand(chunk, &dc.out_audio_format, nbytes);
		if (full) {
			/* the chunk is full, flush it */
			decoder_flush_chunk(decoder);
			notify_signal(&pc.notify);
		}

		data += nbytes;
		length -= nbytes;
	}

	return DECODE_COMMAND_NONE;
}