示例#1
0
ssize_t
ad_read_sndfile(WfDecoder* d, float* out, size_t len)
{
	SndfileDecoder* priv = (SndfileDecoder*)d->d;
	if (!priv) return -1;

	switch(d->info.bit_depth){
		case 32:
			return sf_read_float (priv->sffile, out, len);
		case 16: {
				short* d16 = g_malloc0(len * sizeof(short));
				ssize_t r = sf_read_short (priv->sffile, d16, len);
				int16_to_float(out, d16, d->info.channels, len / d->info.channels, 0);
				g_free(d16);
				return r;
			}
#ifdef DEBUG
		default:
			gwarn("unhandled bit depth: %i", d->info.bit_depth);
#endif
	}

	return -1;
}
示例#2
0
文件: ad_ffmpeg.c 项目: EQ4/samplecat
ssize_t ad_read_ffmpeg(void *sf, float* d, size_t len) {
  ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
  if (!priv) return -1;
  size_t frames = len / priv->channels;

  int written = 0;
  int ret = 0;
  while (ret >= 0 && written < frames) {
    dbg(3, "loop: %i/%i (bl:%lu)",written, frames, priv->m_tmpBufferLen );
    if (priv->seek_frame == 0 && priv->m_tmpBufferLen > 0 ) {
      int s = MIN(priv->m_tmpBufferLen / priv->channels, frames - written );
      int16_to_float(priv->m_tmpBufferStart, d, priv->channels, s , written);
      written += s;
      priv->output_clock+=s;
      s = s * priv->channels;
      priv->m_tmpBufferStart += s;
      priv->m_tmpBufferLen -= s;
      ret = 0;
    } else {
      priv->m_tmpBufferStart = priv->m_tmpBuffer;
      priv->m_tmpBufferLen = 0;

      if (!priv->pkt_ptr || priv->pkt_len < 1) {
        if (priv->packet.data) av_free_packet(&priv->packet);
        ret = av_read_frame(priv->formatContext, &priv->packet);
        if (ret < 0) { dbg(2, "reached end of file."); break; }
        priv->pkt_len = priv->packet.size;
        priv->pkt_ptr = priv->packet.data;
      }

      if (priv->packet.stream_index != priv->audioStream) {
        priv->pkt_ptr = NULL;
        continue;
      }

      /* decode all chunks in packet */
      int data_size= AVCODEC_MAX_AUDIO_FRAME_SIZE;
#if 0 // TODO  ffcompat.h -- this works but is not optimal (channels may not be planar/interleaved)
      AVFrame avf; // TODO statically allocate
      memset(&avf, 0, sizeof(AVFrame)); // not sure if that is needed
      int got_frame = 0;
ret = avcodec_decode_audio4(priv->codecContext, &avf, &got_frame, &priv->packet);
      data_size = avf.linesize[0];
      memcpy(priv->m_tmpBuffer, avf.data[0], avf.linesize[0] * sizeof(uint8_t));
#else // this was deprecated in LIBAVCODEC_VERSION_MAJOR 53
      ret = avcodec_decode_audio3(priv->codecContext, priv->m_tmpBuffer, &data_size, &priv->packet);
#endif

      if (ret < 0 || ret > priv->pkt_len) {
#if 0
        dbg(0, "audio decode error");
        return -1;
#endif
        priv->pkt_len = 0;
        ret = 0;
        continue;
      }

      priv->pkt_len -= ret; priv->pkt_ptr += ret;

      /* sample exact alignment  */
      if (priv->packet.pts != AV_NOPTS_VALUE) {
        priv->decoder_clock = priv->samplerate * av_q2d(priv->formatContext->streams[priv->audioStream]->time_base) * priv->packet.pts;
      } else {
        dbg(0, "!!! NO PTS timestamp in file");
        priv->decoder_clock += (data_size>>1) / priv->channels;
      }

      if (data_size > 0) {
        priv->m_tmpBufferLen+= (data_size>>1); // 2 bytes per sample
      }

      /* align buffer after seek. */
      if (priv->seek_frame > 0) {
        const int diff = priv->output_clock-priv->decoder_clock;
        if (diff < 0) { 
          /* seek ended up past the wanted sample */
          gwarn("audio seek failed.");
          return -1;
        } else if (priv->m_tmpBufferLen < (diff*priv->channels)) {
          /* wanted sample not in current buffer - keep going */
          dbg(2, " !!! seeked sample was not in decoded buffer. frames-to-go: %li", diff);
          priv->m_tmpBufferLen = 0;
        } else if (diff!=0 && data_size > 0) {
          /* wanted sample is in current buffer but not at the beginnning */
          dbg(2, " !!! sync buffer to seek. (diff:%i)", diff);
          priv->m_tmpBufferStart+= diff*priv->codecContext->channels;
          priv->m_tmpBufferLen  -= diff*priv->codecContext->channels;
#if 1
          memmove(priv->m_tmpBuffer, priv->m_tmpBufferStart, priv->m_tmpBufferLen);
          priv->m_tmpBufferStart = priv->m_tmpBuffer;
#endif
          priv->seek_frame = 0;
          priv->decoder_clock += diff;
        } else if (data_size > 0) {
          dbg(2, "Audio exact sync-seek (%"PRIi64" == %"PRIi64")", priv->decoder_clock, priv->seek_frame);
          priv->seek_frame = 0;
        } else {
          dbg(0, "Error: no audio data in packet");
        }
      }
      //dbg(0, "PTS: decoder:%"PRIi64". - want: %"PRIi64, priv->decoder_clock, priv->output_clock);
      //dbg(0, "CLK: frame:  %"PRIi64"  T:%.3fs",priv->decoder_clock, (float) priv->decoder_clock/priv->samplerate);
    }
  }