static gint xmms_mpc_read (xmms_xform_t *xform, xmms_sample_t *buffer, gint len, xmms_error_t *err) { MPC_SAMPLE_FORMAT internal[MPC_DECODER_BUFFER_LENGTH]; xmms_mpc_data_t *data; mpc_uint32_t ret; guint size; data = xmms_xform_private_data_get (xform); size = MIN (data->buffer->len, len); #ifdef HAVE_MPCDEC_OLD if (size <= 0) { ret = mpc_decoder_decode (&data->decoder, internal, NULL, NULL); if (ret == -1) { xmms_error_set (err, XMMS_ERROR_GENERIC, "Musepack decoder failed"); return -1; } ret *= xmms_sample_size_get (XMMS_SAMPLE_FORMAT_FLOAT); ret *= data->info.channels; g_string_append_len (data->buffer, (gchar *) internal, ret); } #else if (size <= 0) { mpc_frame_info frame; frame.buffer = internal; do { ret = mpc_demux_decode (data->demux, &frame); } while (frame.bits != -1 && frame.samples == 0); if (frame.bits == -1 && ret != MPC_STATUS_OK) { xmms_error_set (err, XMMS_ERROR_GENERIC, "Musepack decoder failed"); return -1; } ret = frame.samples; ret *= xmms_sample_size_get (XMMS_SAMPLE_FORMAT_FLOAT); ret *= data->info.channels; g_string_append_len (data->buffer, (gchar *) internal, ret); } #endif /* Update the current size of available data */ size = MIN (data->buffer->len, len); memcpy (buffer, data->buffer->str, size); g_string_erase (data->buffer, 0, size); return size; }
unsigned long decoder_read(unsigned long id, char* adata, unsigned long dsize) { int cur = 0; if(pstreams[id].sample_start) { int z = min(dsize, (pstreams[id].sample_end - pstreams[id].sample_start)); memcpy(adata + cur, ((char*)pstreams[id].sample_buffer) + pstreams[id].sample_start, z); pstreams[id].sample_start += z; cur += z; if(pstreams[id].sample_start >= pstreams[id].sample_end) { pstreams[id].sample_start = 0; } if(cur >= dsize) return cur; } for(;;) { int z; int i = mpc_decoder_decode(&pstreams[id].decoder, pstreams[id].sample_buffer, 0, 0); i *= sizeof(MPC_SAMPLE_FORMAT); i *= pstreams[id].info.channels; if(i == 0) break; z = min(i, dsize - cur); memcpy(adata + cur, pstreams[id].sample_buffer, z); cur += z; if(cur >= dsize) { if(i > z) pstreams[id].sample_start = z; pstreams[id].sample_end = i; return cur; } pstreams[id].sample_start = 0; } return cur; }
int64 Read_(int16 *buffer, int64 frames) { // MPC_SAMPLE_FORMAT MPCBuffer[MPC_DECODER_BUFFER_LENGTH]; //MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; // uint32 MPCBufferIn; int16 *cowbuf = (int16 *)buffer; int32 toread = frames * 2; while(toread > 0) { int32 tmplen; if(!MPCBufferIn) { int status = mpc_decoder_decode(&MPCDecoder, MPCBuffer, 0, 0); if(status < 0) break; MPCBufferIn = status * 2; MPCBufferOffs = 0; } tmplen = MPCBufferIn; if(tmplen >= toread) tmplen = toread; for(int x = 0; x < tmplen; x++) { int32 samp = MPCBuffer[MPCBufferOffs + x]; samp >> 14; //if(samp < - 32768 || samp > 32767) // This happens with some MPCs of ripped games I've tested, and it's not just 1 or 2 over, and I don't know why! // printf("MPC Sample out of range: %d\n", samp); *cowbuf = (int16)samp; cowbuf++; } MPCBufferOffs += tmplen; toread -= tmplen; MPCBufferIn -= tmplen; } return(frames - toread / 2); }
static void gst_musepackdec_loop (GstPad * sinkpad) { GstMusepackDec *musepackdec; GstFlowReturn flow; GstBuffer *out; #ifdef MPC_IS_OLD_API guint32 update_acc, update_bits; #else mpc_frame_info frame; mpc_status err; #endif gint num_samples, samplerate, bitspersample; musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad)); samplerate = g_atomic_int_get (&musepackdec->rate); if (samplerate == 0) { if (!gst_musepack_stream_init (musepackdec)) goto pause_task; gst_musepackdec_send_newsegment (musepackdec); samplerate = g_atomic_int_get (&musepackdec->rate); } bitspersample = g_atomic_int_get (&musepackdec->bps); flow = gst_pad_alloc_buffer_and_set_caps (musepackdec->srcpad, -1, MPC_DECODER_BUFFER_LENGTH * 4, GST_PAD_CAPS (musepackdec->srcpad), &out); if (flow != GST_FLOW_OK) { GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow)); goto pause_task; } #ifdef MPC_IS_OLD_API num_samples = mpc_decoder_decode (musepackdec->d, (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits); if (num_samples < 0) { GST_ERROR_OBJECT (musepackdec, "Failed to decode sample"); GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL)); goto pause_task; } else if (num_samples == 0) { goto eos_and_pause; } #else frame.buffer = (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out); err = mpc_demux_decode (musepackdec->d, &frame); if (err != MPC_STATUS_OK) { GST_ERROR_OBJECT (musepackdec, "Failed to decode sample"); GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL)); goto pause_task; } else if (frame.bits == -1) { goto eos_and_pause; } num_samples = frame.samples; #endif GST_BUFFER_SIZE (out) = num_samples * bitspersample; GST_BUFFER_OFFSET (out) = musepackdec->segment.last_stop; GST_BUFFER_TIMESTAMP (out) = gst_util_uint64_scale_int (musepackdec->segment.last_stop, GST_SECOND, samplerate); GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate); musepackdec->segment.last_stop += num_samples; GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out))); flow = gst_pad_push (musepackdec->srcpad, out); if (flow != GST_FLOW_OK) { GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow)); goto pause_task; } /* check if we're at the end of a configured segment */ if (musepackdec->segment.stop != -1 && musepackdec->segment.last_stop >= musepackdec->segment.stop) { gint64 stop_time; GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment"); if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0) goto eos_and_pause; GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message"); stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop, GST_SECOND, samplerate); gst_element_post_message (GST_ELEMENT (musepackdec), gst_message_new_segment_done (GST_OBJECT (musepackdec), GST_FORMAT_TIME, stop_time)); goto pause_task; } return; eos_and_pause: { GST_DEBUG_OBJECT (musepackdec, "sending EOS event"); gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ()); /* fall through to pause */ } pause_task: { GST_DEBUG_OBJECT (musepackdec, "Pausing task"); gst_pad_pause_task (sinkpad); return; } }
int cdrfile_read_audio_sector(CDRFile *p_cdrfile, void *buf, uint8 *SubPWBuf, lsn_t lsn) { if(SubPWBuf) { memset(SubPWBuf, 0, 96); MakeSubQ(p_cdrfile, lsn, SubPWBuf); } if(p_cdrfile->p_cdio) { if(cdio_read_audio_sector(p_cdrfile->p_cdio, buf, lsn) < 0) { memset(buf, 0, 2352); return(0); } Endian_A16_LE_to_NE(buf, 588 * 2); return(1); } else { track_t track; for(track = p_cdrfile->FirstTrack; track < (p_cdrfile->FirstTrack + p_cdrfile->NumTracks); track++) { if(lsn >= (p_cdrfile->Tracks[track].LSN - p_cdrfile->Tracks[track].pregap) && lsn < (p_cdrfile->Tracks[track].LSN + p_cdrfile->Tracks[track].sectors)) { if(lsn < p_cdrfile->Tracks[track].LSN) { //puts("Pregap read"); memset(buf, 0, 2352); } else { if(p_cdrfile->Tracks[track].sf) { long SeekPos = (p_cdrfile->Tracks[track].FileOffset / 4) + (lsn - p_cdrfile->Tracks[track].LSN) * 588; //printf("%d, %d\n", lsn, p_cdrfile->Tracks[track].LSN); if(p_cdrfile->Tracks[track].LastSamplePos != SeekPos) { //printf("Seek: %d %d\n", SeekPos, p_cdrfile->Tracks[track].LastSamplePos); sf_seek(p_cdrfile->Tracks[track].sf, SeekPos, SEEK_SET); p_cdrfile->Tracks[track].LastSamplePos = SeekPos; } sf_count_t readcount = sf_read_short(p_cdrfile->Tracks[track].sf, (short*)buf, 588 * 2); p_cdrfile->Tracks[track].LastSamplePos += readcount / 2; } else if(p_cdrfile->Tracks[track].ovfile)// vorbis { int cursection = 0; if(p_cdrfile->Tracks[track].LastSamplePos != 588 * (lsn - p_cdrfile->Tracks[track].LSN)) { ov_pcm_seek((OggVorbis_File *)p_cdrfile->Tracks[track].ovfile, (lsn - p_cdrfile->Tracks[track].LSN) * 588); p_cdrfile->Tracks[track].LastSamplePos = 588 * (lsn - p_cdrfile->Tracks[track].LSN); } long toread = 2352; while(toread > 0) { long didread = ov_read((OggVorbis_File *)p_cdrfile->Tracks[track].ovfile, (char*)buf, toread, &cursection); if(didread == 0) { memset(buf, 0, toread); toread = 0; break; } buf = (uint8 *)buf + didread; toread -= didread; p_cdrfile->Tracks[track].LastSamplePos += didread / 4; } } // end if vorbis else if(p_cdrfile->Tracks[track].MPCReaderFile) // MPC { //printf("%d %d\n", (lsn - p_cdrfile->Tracks[track].LSN), p_cdrfile->Tracks[track].LastSamplePos); if(p_cdrfile->Tracks[track].LastSamplePos != 1176 * (lsn - p_cdrfile->Tracks[track].LSN)) { mpc_decoder_seek_sample(p_cdrfile->Tracks[track].MPCDecoder, 588 * (lsn - p_cdrfile->Tracks[track].LSN)); p_cdrfile->Tracks[track].LastSamplePos = 1176 * (lsn - p_cdrfile->Tracks[track].LSN); } //MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; // MPC_SAMPLE_FORMAT MPCBuffer[MPC_DECODER_BUFFER_LENGTH]; // uint32 MPCBufferIn; int16 *cowbuf = (int16 *)buf; int32 toread = 1176; while(toread) { int32 tmplen; if(!p_cdrfile->Tracks[track].MPCBufferIn) { int status = mpc_decoder_decode(p_cdrfile->Tracks[track].MPCDecoder, p_cdrfile->Tracks[track].MPCBuffer, 0, 0); if(status < 0) { printf("Bah\n"); break; } p_cdrfile->Tracks[track].MPCBufferIn = status * 2; p_cdrfile->Tracks[track].MPCBufferOffs = 0; } tmplen = p_cdrfile->Tracks[track].MPCBufferIn; if(tmplen >= toread) tmplen = toread; for(int x = 0; x < tmplen; x++) { int32 samp = p_cdrfile->Tracks[track].MPCBuffer[p_cdrfile->Tracks[track].MPCBufferOffs + x] >> 14; //if(samp < - 32768 || samp > 32767) // This happens with some MPCs of ripped games I've tested, and it's not just 1 or 2 over, and I don't know why! // printf("MPC Sample out of range: %d\n", samp); *cowbuf = (int16)samp; cowbuf++; } p_cdrfile->Tracks[track].MPCBufferOffs += tmplen; toread -= tmplen; p_cdrfile->Tracks[track].LastSamplePos += tmplen; p_cdrfile->Tracks[track].MPCBufferIn -= tmplen; } } else // Binary, woo. { long SeekPos = p_cdrfile->Tracks[track].FileOffset + 2352 * (lsn - p_cdrfile->Tracks[track].LSN); //(lsn - p_cdrfile->Tracks[track].index - p_cdrfile->Tracks[track].pregap); if(p_cdrfile->Tracks[track].SubchannelMode) SeekPos += 96 * (lsn - p_cdrfile->Tracks[track].LSN); if(!fseek(p_cdrfile->Tracks[track].fp, SeekPos, SEEK_SET)) { size_t didread = fread(buf, 1, 2352, p_cdrfile->Tracks[track].fp); if(didread != 2352) { if(didread < 0) didread = 0; memset((uint8*)buf + didread, 0, 2352 - didread); } if(SubPWBuf && p_cdrfile->Tracks[track].SubchannelMode) { fread(SubPWBuf, 1, 96, p_cdrfile->Tracks[track].fp); } if(p_cdrfile->Tracks[track].RawAudioMSBFirst) Endian_A16_BE_to_NE(buf, 588 * 2); else Endian_A16_LE_to_NE(buf, 588 * 2); } else memset(buf, 0, 2352); } } // end if audible part of audio track read. break; } // End if LSN is in range } // end track search loop if(track == (p_cdrfile->FirstTrack + p_cdrfile->NumTracks)) { memset(buf, 0, 2352); return(0); } return(1); }