static gint xmms_opus_read (xmms_xform_t *xform, gpointer buf, gint len, xmms_error_t *err) { gint ret = 0; gint c; xmms_opus_data_t *data; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); ret = xmms_opus_op_read (data->opusfile, (gchar *) buf, len, G_BYTE_ORDER == G_BIG_ENDIAN, xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16), 1, &c); if (ret < 0) { return -1; } if (ret && c != data->current) { xmms_opus_read_metadata (xform, data); data->current = c; } return ret; }
/** * Get number of bytes used for one sample length worth of music. * * That is, (size of one sample) * channels. */ gint xmms_sample_frame_size_get (const xmms_stream_type_t *st) { gint format, channels; format = xmms_stream_type_get_int (st, XMMS_STREAM_TYPE_FMT_FORMAT); channels = xmms_stream_type_get_int (st, XMMS_STREAM_TYPE_FMT_CHANNELS); return xmms_sample_size_get (format) * channels; }
static gint xmms_mad_read (xmms_xform_t *xform, gpointer buf, gint len, xmms_error_t *err) { xmms_mad_data_t *data; xmms_samples16_t *out = (xmms_samples16_t *)buf; gint ret; gint j; gint read = 0; data = xmms_xform_private_data_get (xform); j = 0; while (read < len) { /* use already synthetized frame first */ if (data->synthpos < data->synth.pcm.length) { out[j++] = scale_linear (data->synth.pcm.samples[0][data->synthpos]); if (data->channels == 2) { out[j++] = scale_linear (data->synth.pcm.samples[1][data->synthpos]); read += 2 * xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16); } else { read += xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16); } data->synthpos++; continue; } /* then try to decode another frame */ if (mad_frame_decode (&data->frame, &data->stream) != -1) { /* mad_synthpop_frame - go Depeche! */ mad_synth_frame (&data->synth, &data->frame); if (data->frames_to_skip) { data->frames_to_skip--; data->synthpos = 0x7fffffff; } else if (data->samples_to_skip) { if (data->samples_to_skip > data->synth.pcm.length) { data->synthpos = 0x7fffffff; data->samples_to_skip -= data->synth.pcm.length; } else { data->synthpos = data->samples_to_skip; data->samples_to_skip = 0; } } else { if (data->samples_to_play == 0) { return read; } else if (data->samples_to_play > 0) { if (data->synth.pcm.length > data->samples_to_play) { data->synth.pcm.length = data->samples_to_play; } data->samples_to_play -= data->synth.pcm.length; } data->synthpos = 0; } continue; } /* if there is no frame to decode stream more data */ if (data->stream.next_frame) { guchar *buffer = data->buffer; const guchar *nf = data->stream.next_frame; memmove (data->buffer, data->stream.next_frame, data->buffer_length = (&buffer[data->buffer_length] - nf)); } ret = xmms_xform_read (xform, (gchar *)data->buffer + data->buffer_length, 4096 - data->buffer_length, err); if (ret <= 0) { return ret; } data->buffer_length += ret; mad_stream_buffer (&data->stream, data->buffer, data->buffer_length); } return read; }
static gint xmms_faad_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err) { xmms_faad_data_t *data; xmms_error_t error; NeAACDecFrameInfo frameInfo; gpointer sample_buffer; guint size, bytes_read = 0; data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); size = MIN (data->outbuf->len, len); while (size == 0) { gboolean need_read; /* MP4 demuxer always gives full packets so we need different handling */ if (data->filetype == FAAD_TYPE_MP4) need_read = (data->buffer_length == 0); else need_read = (data->buffer_length < data->buffer_size); if (need_read) { bytes_read = xmms_xform_read (xform, (gchar *) data->buffer + data->buffer_length, data->buffer_size - data->buffer_length, &error); if (bytes_read <= 0 && data->buffer_length == 0) { XMMS_DBG ("EOF"); return 0; } data->buffer_length += bytes_read; } sample_buffer = NeAACDecDecode (data->decoder, &frameInfo, data->buffer, data->buffer_length); g_memmove (data->buffer, data->buffer + frameInfo.bytesconsumed, data->buffer_length - frameInfo.bytesconsumed); data->buffer_length -= frameInfo.bytesconsumed; bytes_read = frameInfo.samples * xmms_sample_size_get (data->sampleformat); if (bytes_read > 0 && frameInfo.error == 0) { gint32 temp, toskip = 0; if (data->samplerate != frameInfo.samplerate || data->channels != frameInfo.channels) { /* We should inform output to change parameters somehow */ XMMS_DBG ("Output format changed in the middle of a read!"); data->samplerate = frameInfo.samplerate; data->channels = frameInfo.channels; } if (xmms_xform_auxdata_get_int (xform, "frame_offset", &temp)) { toskip = (temp * frameInfo.channels * xmms_sample_size_get (data->sampleformat)); } if (xmms_xform_auxdata_get_int (xform, "frame_duration", &temp)) { bytes_read = (temp * frameInfo.channels * xmms_sample_size_get (data->sampleformat)); } g_string_append_len (data->outbuf, sample_buffer + toskip, bytes_read - toskip); } else if (frameInfo.error > 0) { XMMS_DBG ("ERROR %d in faad decoding: %s", frameInfo.error, NeAACDecGetErrorMessage (frameInfo.error)); return -1; } size = MIN (data->outbuf->len, len); } memcpy (buf, data->outbuf->str, size); g_string_erase (data->outbuf, 0, size); return size; }