Пример #1
0
SInt64 SFB::Audio::MusepackDecoder::_SeekToFrame(SInt64 frame)
{
	mpc_status result = mpc_demux_seek_sample(mDemux, (mpc_uint64_t)frame);
	if(MPC_STATUS_OK == result)
		mCurrentFrame = frame;

	return ((MPC_STATUS_OK == result) ? mCurrentFrame : -1);
}
Пример #2
0
bool CDAFReader_MPC::Seek_(uint64 frame_offset)
{
    MPCBufferOffs = 0;
    MPCBufferIn = 0;

    if(mpc_demux_seek_sample(demux, frame_offset) < 0)
        return(false);

    return(true);
}
Пример #3
0
static gint64
xmms_mpc_seek (xmms_xform_t *xform, gint64 offset,
               xmms_xform_seek_mode_t whence, xmms_error_t *err)
{
    xmms_mpc_data_t *data;
    data = xmms_xform_private_data_get (xform);

    g_return_val_if_fail (whence == XMMS_XFORM_SEEK_SET, -1);

#ifdef HAVE_MPCDEC_OLD
    mpc_decoder_seek_sample (&data->decoder, offset);
#else
    mpc_demux_seek_sample (data->demux, offset);
#endif
    g_string_erase (data->buffer, 0, data->buffer->len);

    return offset;
}
Пример #4
0
static gboolean
gst_musepackdec_handle_seek_event (GstMusepackDec * dec, GstEvent * event)
{
  GstSeekType start_type, stop_type;
  GstSeekFlags flags;
  GstSegment segment;
  GstFormat format;
  gboolean flush;
  gdouble rate;
  gint64 start, stop;
  gint samplerate;

  gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
      &stop_type, &stop);

  if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) {
    GST_DEBUG_OBJECT (dec, "seek failed: only TIME or DEFAULT format allowed");
    return FALSE;
  }

  samplerate = g_atomic_int_get (&dec->rate);

  if (format == GST_FORMAT_TIME) {
    if (start_type != GST_SEEK_TYPE_NONE)
      start = gst_util_uint64_scale_int (start, samplerate, GST_SECOND);
    if (stop_type != GST_SEEK_TYPE_NONE)
      stop = gst_util_uint64_scale_int (stop, samplerate, GST_SECOND);
  }

  flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);

  if (flush)
    gst_pad_push_event (dec->srcpad, gst_event_new_flush_start ());
  else
    gst_pad_pause_task (dec->sinkpad);  /* not _stop_task()? */

  GST_PAD_STREAM_LOCK (dec->sinkpad);

  /* operate on segment copy until we know the seek worked */
  segment = dec->segment;

  gst_segment_do_seek (&segment, rate, GST_FORMAT_DEFAULT,
      flags, start_type, start, stop_type, stop, NULL);

  gst_pad_push_event (dec->sinkpad, gst_event_new_flush_stop (TRUE));

  GST_DEBUG_OBJECT (dec, "segment: [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT
      "] = [%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "]",
      segment.start, segment.stop,
      GST_TIME_ARGS (segment.start * GST_SECOND / dec->rate),
      GST_TIME_ARGS (segment.stop * GST_SECOND / dec->rate));

  GST_DEBUG_OBJECT (dec, "performing seek to sample %" G_GINT64_FORMAT,
      segment.start);

  if (segment.start >= segment.duration) {
    GST_WARNING_OBJECT (dec, "seek out of bounds");
    goto failed;
  }
  if (mpc_demux_seek_sample (dec->d, segment.start) != MPC_STATUS_OK)
    goto failed;

  if ((flags & GST_SEEK_FLAG_SEGMENT) == GST_SEEK_FLAG_SEGMENT) {
    GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");

    gst_element_post_message (GST_ELEMENT (dec),
        gst_message_new_segment_start (GST_OBJECT (dec), GST_FORMAT_TIME,
            gst_util_uint64_scale_int (segment.start, GST_SECOND, dec->rate)));
  }

  if (flush) {
    gst_pad_push_event (dec->srcpad, gst_event_new_flush_stop (TRUE));
  }

  segment.position = segment.start;
  dec->segment = segment;
  gst_musepackdec_send_newsegment (dec);

  GST_DEBUG_OBJECT (dec, "seek successful");

  gst_pad_start_task (dec->sinkpad,
      (GstTaskFunction) gst_musepackdec_loop, dec->sinkpad, NULL);

  GST_PAD_STREAM_UNLOCK (dec->sinkpad);

  return TRUE;

failed:
  {
    GST_WARNING_OBJECT (dec, "seek failed");
    GST_PAD_STREAM_UNLOCK (dec->sinkpad);
    return FALSE;
  }
}
Пример #5
0
/* This is the codec entry point. */
enum codec_status codec_main(void)
{
    mpc_int64_t samplesdone;
    uint32_t frequency;     /* 0.1 kHz accuracy */
    uint32_t elapsed_time;  /* milliseconds */
    uint32_t byterate;      /* bytes per second */
    mpc_status status;
    mpc_reader reader;
    mpc_streaminfo info;
    mpc_frame_info frame;
    mpc_demux *demux = NULL;
    int retval = CODEC_OK;
    
    frame.buffer = sample_buffer;
    
    /* musepack's sample representation is 18.14
     * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
    
    /* Create a decoder instance */
    reader.read     = read_impl;
    reader.seek     = seek_impl;
    reader.tell     = tell_impl;
    reader.get_size = get_size_impl;

next_track:    
    if (codec_init()) 
    {
        retval = CODEC_ERROR;
        goto exit;
    }

    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    /* Initialize demux/decoder. */
    demux = mpc_demux_init(&reader);
    if (NULL == demux)
    {
        retval = CODEC_ERROR;
        goto done;
    }
    /* Read file's streaminfo data. */
    mpc_demux_get_info(demux, &info);
    
    byterate  = (mpc_uint32_t)(info.average_bitrate) / 8;
    frequency = info.sample_freq / 100; /* 0.1 kHz accuracy */
    ci->configure(DSP_SWITCH_FREQUENCY, info.sample_freq);

    /* Remark: rockbox offset is the file offset in bytes. So, estimate the 
     * sample seek position from the file offset, the sampling frequency and
     * the bitrate. As the saved position is exactly calculated the reverse way 
     * there is no loss of information except rounding. */
    samplesdone = 100 * ((mpc_uint64_t)(ci->id3->offset * frequency) / byterate);
        
    /* Set up digital signal processing for correct number of channels */
    /* NOTE: current musepack format only allows for stereo files
       but code is here to handle other configurations anyway */
    if      (info.channels == 2)
        ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
    else if (info.channels == 1)
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    else 
    {
       retval = CODEC_ERROR;
       goto done;
    }
    
    codec_set_replaygain(ci->id3);

    /* Resume to saved sample offset. */
    if (samplesdone > 0) 
    {
        if (mpc_demux_seek_sample(demux, samplesdone) == MPC_STATUS_OK) 
        {
            elapsed_time = (samplesdone*10)/frequency;
            ci->set_elapsed(elapsed_time);
        } 
        else 
        {
            samplesdone = 0;
        }
    }

    /* This is the decoding loop. */
    do 
    {
        /* Complete seek handler. */
        if (ci->seek_time) 
        {
            mpc_int64_t new_offset = ((ci->seek_time - 1)/10)*frequency;
            if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) 
            {
                samplesdone = new_offset;
                ci->set_elapsed(ci->seek_time);
            }
            ci->seek_complete();
        }
        
        /* Stop or skip occured, exit decoding loop. */
        if (ci->stop_codec || ci->new_track)
            break;

        /* Decode one frame. */
        status = mpc_demux_decode(demux, &frame);
        ci->yield();
        if (frame.bits == -1)
        {
            /* Decoding error, exit decoding loop. */
            retval = (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR;
            goto done;
        } 
        else 
        {
            /* Decoding passed, insert samples to PCM buffer. */
            ci->pcmbuf_insert(frame.buffer,
                              frame.buffer + MPC_FRAME_LENGTH,
                              frame.samples);
            samplesdone += frame.samples;
            elapsed_time = (samplesdone*10)/frequency;
            ci->set_elapsed(elapsed_time);
            /* Remark: rockbox offset is the file offset in bytes. So estimate 
             * this offset from the samples, sampling frequency and bitrate */
            ci->set_offset( (samplesdone * byterate)/(frequency*100) );
        }
    } while (true);

done:
    if (ci->request_next_track())
        goto next_track;

exit:
    return retval;
}
Пример #6
0
int main(int argc, char **argv)
{
	MPC_SAMPLE_FORMAT album_max = 0;
	mpc_uint16_t album_gain;
	mpc_uint16_t album_peak;
	mpc_uint16_t * title_gain;
	mpc_uint16_t * title_peak;
	mpc_uint32_t * header_pos;
	int j;

	printf(About);

	if (argc < 2) {
		usage(argv[0]);
		return 0;
	}

	title_gain = malloc((sizeof(mpc_uint16_t) * 2 + sizeof(mpc_uint32_t)) * (argc - 1));
	title_peak = title_gain + (argc - 1);
	header_pos = (mpc_uint32_t *) (title_peak + (argc - 1));

	for (j = 1; j < argc; j++) {
		MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
		MPC_SAMPLE_FORMAT title_max = 0, chap_max;
		mpc_uint16_t * chap_gain, * chap_peak;
		mpc_reader reader;
		mpc_demux* demux;
		mpc_streaminfo si;
		mpc_status err;
		int chap_nb, chap = 0;
		mpc_uint64_t cur_sample = 1, next_chap_sample = mpc_int64_max;

		err = mpc_reader_init_stdio(&reader, argv[j]);
		if (err < 0) return !MPC_STATUS_OK;

		demux = mpc_demux_init(&reader);
		if (!demux) return !MPC_STATUS_OK;
		mpc_demux_get_info(demux,  &si);

		chap_nb = mpc_demux_chap_nb(demux);
		mpc_demux_seek_sample(demux, 0);
		if (chap_nb > 0) {
			mpc_chap_info * chap_info = mpc_demux_chap(demux, chap);
			next_chap_sample = chap_info->sample;
			chap_gain = malloc(sizeof(mpc_uint16_t) * 2 * chap_nb);
			chap_peak = chap_gain + chap_nb;
		}

		if (j == 1) gain_init_analysis ( si.sample_freq );

		while (1) {
			mpc_frame_info frame;
			int i = 0;

			frame.buffer = sample_buffer;
			mpc_demux_decode(demux, &frame);
			if (frame.bits == -1) break;

			while (next_chap_sample < cur_sample + frame.samples) {
				int sample_nb = (int)(next_chap_sample - cur_sample);

				chap_max = _max(chap_max, analyze_get_max(sample_buffer + 2 * i, sample_nb));

				if (chap == 0) // first samples are not in a chapter
					gain_get_chapter();
				else {
					chap_gain[chap - 1] = (mpc_uint16_t) (gain_get_chapter() * 256);
					chap_peak[chap - 1] = (mpc_uint16_t) (log10(chap_max * (1 << 15)) * 20 * 256);
				}
				chap++;
				title_max = _max(title_max, chap_max);
				chap_max = 0;
				i += sample_nb;
				cur_sample = next_chap_sample;
				if (chap < chap_nb) {
					mpc_chap_info * chap_info = mpc_demux_chap(demux, chap);
					next_chap_sample = chap_info->sample;
				} else
					next_chap_sample = mpc_int64_max;
			}

			chap_max = _max(chap_max, analyze_get_max(sample_buffer + 2 * i, frame.samples - i));
			cur_sample += frame.samples - i;
		}

		if (chap_nb > 0) {
			chap_gain[chap - 1] = (mpc_uint16_t) (gain_get_chapter() * 256);
			chap_peak[chap - 1] = (mpc_uint16_t) (log10(chap_max * (1 << 15)) * 20 * 256);
			write_chaps_gain(demux, argv[j], chap_gain, chap_peak);
		}

		title_max = _max(title_max, chap_max);
		album_max = _max(album_max, title_max);

		title_gain[j-1] = (mpc_uint16_t) (gain_get_title() * 256);
		title_peak[j-1] = (mpc_uint16_t) (log10(title_max * (1 << 15)) * 20 * 256);
		header_pos[j-1] = si.header_position + 4;

		mpc_demux_exit(demux);
		mpc_reader_exit_stdio(&reader);
		if (chap_nb > 0)
			free(chap_gain);
	}

	album_gain = (mpc_uint16_t) (gain_get_album() * 256);
	album_peak = (mpc_uint16_t) (log10(album_max * (1 << 15)) * 20 * 256);

	for (j = 0; j < argc - 1; j++) {
		unsigned char buffer[64];
		mpc_bits_reader r;
		mpc_block b;
		mpc_uint64_t size;
		FILE * file;

		file = fopen( argv[j + 1], "r+b");
		if (file == 0) {
			fprintf(stderr, "Can't open file \"%s\" for writing\n", argv[j + 1]);
			continue;
		}
		fseek(file, header_pos[j] - 4, SEEK_SET);
		fread(buffer, 1, 16, file);
		if (memcmp(buffer, "MPCK", 4) != 0) {
			fprintf(stderr, "Unsupported file format, not a sv8 file : %s\n", argv[j + 1]);
			fclose(file);
			continue;
		}
		r.buff = buffer + 4;
		r.count = 8;

		for(;;) {
			size = mpc_bits_get_block(&r, &b);
			if (mpc_check_key(b.key) != MPC_STATUS_OK) break;

			if (memcmp(b.key, "RG", 2) == 0) break;
			header_pos[j] += b.size + size;
			fseek(file, header_pos[j], SEEK_SET);
			fread(buffer, 1, 16, file);
			r.buff = buffer;
			r.count = 8;
		}

		if (memcmp(b.key, "RG", 2) != 0 || b.size < 9) { //check for the loop above having aborted without finding the packet we want to update
			fprintf(stderr, "Unsupported file format or corrupted file : %s\n", argv[j + 1]);
			fclose(file);
			continue;
		}
		header_pos[j] += size;

		buffer[size] = 1; // replaygain version
		buffer[size + 1] = title_gain[j] >> 8;
		buffer[size + 2] = title_gain[j] & 0xFF;
		buffer[size + 3] = title_peak[j] >> 8;
		buffer[size + 4] = title_peak[j] & 0xFF;
		buffer[size + 5] = album_gain >> 8;
		buffer[size + 6] = album_gain & 0xFF;
		buffer[size + 7] = album_peak >> 8;
		buffer[size + 8] = album_peak & 0xFF;

		fseek(file, header_pos[j], SEEK_SET);
		fwrite(buffer + size, 1, b.size, file);
		fclose(file);
	}

	free(title_gain);

    return 0;
}