Example #1
1
/*!
 * \brief Create a new OGG/Speex filestream and set it up for reading.
 * \param fs File that points to on disk storage of the OGG/Speex data.
 * \return The new filestream.
 */
static int ogg_speex_open(struct ast_filestream *fs)
{
	char *buffer;
	size_t bytes;
	struct speex_desc *s = (struct speex_desc *)fs->_private;
	SpeexHeader *hdr = NULL;
	int i, result, expected_rate;

	expected_rate = ast_format_get_sample_rate(fs->fmt->format);
	s->serialno = -1;
	ogg_sync_init(&s->oy);

	buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
	bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
	ogg_sync_wrote(&s->oy, bytes);

	result = ogg_sync_pageout(&s->oy, &s->og);
	if (result != 1) {
		if(bytes < BLOCK_SIZE) {
			ast_log(LOG_ERROR, "Run out of data...\n");
		} else {
			ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
		}
		ogg_sync_clear(&s->oy);
		return -1;
	}

	ogg_stream_init(&s->os, ogg_page_serialno(&s->og));
	if (ogg_stream_pagein(&s->os, &s->og) < 0) {
		ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
		goto error;
	}

	if (read_packet(fs) < 0) {
		ast_log(LOG_ERROR, "Error reading initial header packet.\n");
		goto error;
	}

	hdr = speex_packet_to_header((char*)s->op.packet, s->op.bytes);
	if (memcmp(hdr->speex_string, "Speex   ", 8)) {
		ast_log(LOG_ERROR, "OGG container does not contain Speex audio!\n");
		goto error;
	}
	if (hdr->frames_per_packet != 1) {
		ast_log(LOG_ERROR, "Only one frame-per-packet OGG/Speex files are currently supported!\n");
		goto error;
	}
	if (hdr->nb_channels != 1) {
		ast_log(LOG_ERROR, "Only monophonic OGG/Speex files are currently supported!\n");
		goto error;
	}
	if (hdr->rate != expected_rate) {
		ast_log(LOG_ERROR, "Unexpected sampling rate (%d != %d)!\n",
			hdr->rate, expected_rate);
		goto error;
	}

	/* this packet is the comment */
	if (read_packet(fs) < 0) {
		ast_log(LOG_ERROR, "Error reading comment packet.\n");
		goto error;
	}
	for (i = 0; i < hdr->extra_headers; i++) {
		if (read_packet(fs) < 0) {
			ast_log(LOG_ERROR, "Error reading extra header packet %d.\n", i+1);
			goto error;
		}
	}
	speex_header_free(hdr);

	return 0;
error:
	if (hdr) {
		speex_header_free(hdr);
	}
	ogg_stream_clear(&s->os);
	ogg_sync_clear(&s->oy);
	return -1;
}
Example #2
0
ogg_codec_t *initial_speex_page (format_plugin_t *plugin, ogg_page *page)
{
    ogg_state_t *ogg_info = plugin->_state;
    ogg_codec_t *codec = acalloc (1, sizeof (ogg_codec_t));
    ogg_packet packet;
    SpeexHeader *header;

    ogg_stream_init (&codec->os, ogg_page_serialno (page));
    ogg_stream_pagein (&codec->os, page);

    ogg_stream_packetout (&codec->os, &packet);

    DEBUG0("checking for speex codec");
    header = speex_packet_to_header ((char*)packet.packet, packet.bytes);
    if (header == NULL)
    {
        ogg_stream_clear (&codec->os);
        free (header);
        free (codec);
        return NULL;
    }
    INFO0 ("seen initial speex header");
    codec->process_page = process_speex_page;
    codec->codec_free = speex_codec_free;
    codec->headers = 1;
    format_ogg_attach_header (ogg_info, page);
    free (header);
    return codec;
}
Example #3
0
static av_cold int libspeex_decode_init(AVCodecContext *avctx)
{
    LibSpeexContext *s = avctx->priv_data;
    const SpeexMode *mode;

    // defaults in the case of a missing header
    if (avctx->sample_rate <= 8000)
        mode = &speex_nb_mode;
    else if (avctx->sample_rate <= 16000)
        mode = &speex_wb_mode;
    else
        mode = &speex_uwb_mode;

    if (avctx->extradata_size >= 80)
        s->header = speex_packet_to_header(avctx->extradata, avctx->extradata_size);

    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
    if (s->header) {
        avctx->sample_rate = s->header->rate;
        avctx->channels    = s->header->nb_channels;
        s->frame_size      = s->header->frame_size;

        mode = speex_lib_get_mode(s->header->mode);
        if (!mode) {
            av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", s->header->mode);
            return AVERROR_INVALIDDATA;
        }
    } else
        av_log(avctx, AV_LOG_INFO, "Missing Speex header, assuming defaults.\n");

    if (avctx->channels > 2) {
        av_log(avctx, AV_LOG_ERROR, "Only stereo and mono are supported.\n");
        return AVERROR(EINVAL);
    }

    speex_bits_init(&s->bits);
    s->dec_state = speex_decoder_init(mode);
    if (!s->dec_state) {
        av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
        return -1;
    }

    if (!s->header) {
        speex_decoder_ctl(s->dec_state, SPEEX_GET_FRAME_SIZE, &s->frame_size);
    }

    if (avctx->channels == 2) {
        SpeexCallback callback;
        callback.callback_id = SPEEX_INBAND_STEREO;
        callback.func = speex_std_stereo_request_handler;
        callback.data = &s->stereo;
        s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
        speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
    }

    avcodec_get_frame_defaults(&s->frame);
    avctx->coded_frame = &s->frame;

    return 0;
}
Example #4
0
static void *process_header (struct spx_data *data)
{
	void *st;
	const SpeexMode *mode;
	int modeID;
	SpeexCallback callback;
	int enhance = ENHANCE_AUDIO;

	data->header = speex_packet_to_header ((char*)data->op.packet,
			data->op.bytes);
	if (!data->header) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"Can't open speex file: can't read header");
		return NULL;
	}

	if (data->header->mode >= SPEEX_NB_MODES) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"Can't open speex file: Mode number %"PRId32
				" does not exist in this version",
				data->header->mode);
		return NULL;
	}

	modeID = data->header->mode;
	mode = speex_mode_list[modeID];

	if (mode->bitstream_version < data->header->mode_bitstream_version) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"Can't open speex file: The file was encoded "
				"with a newer version of Speex.");
		return NULL;
	}

	if (mode->bitstream_version > data->header->mode_bitstream_version) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"Can't open speex file: The file was encoded "
				"with an older version of Speex.");
		return NULL;
	}

	st = speex_decoder_init (mode);
	speex_decoder_ctl(st, SPEEX_SET_ENH, &enhance);
	speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, &data->frame_size);

	callback.callback_id = SPEEX_INBAND_STEREO;
	callback.func = speex_std_stereo_request_handler;
	callback.data = &data->stereo;
	speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback);
	speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &data->header->rate);

	return st;
}
Example #5
0
ogg_codec_t *initial_speex_page (format_plugin_t *plugin, ogg_page *page)
{
    ogg_state_t *ogg_info = plugin->_state;
    ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t));
    ogg_packet packet;
    SpeexHeader *header;

    ogg_stream_init (&codec->os, ogg_page_serialno (page));
    ogg_stream_pagein (&codec->os, page);

    ogg_stream_packetout (&codec->os, &packet);

    /* Check for te first packet to be at least of the minimal size for a Speex header.
     * The header size is 80 bytes as per specs. You can find the specs here:
     * https://speex.org/docs/manual/speex-manual/node8.html#SECTION00830000000000000000
     *
     * speex_packet_to_header() will also check the header size for us. However
     * that function generates noise on stderr in case the header is too short.
     * This is dangerous as we may have closed stderr already and the handle may be use
     * again for something else.
     */
    if (packet.bytes < 80) {
        return NULL;
    }

    ICECAST_LOG_DEBUG("checking for speex codec");
    header = speex_packet_to_header ((char*)packet.packet, packet.bytes);
    if (header == NULL)
    {
        ogg_stream_clear (&codec->os);
        free (header);
        free (codec);
        return NULL;
    }
    ICECAST_LOG_INFO("seen initial speex header");
    codec->process_page = process_speex_page;
    codec->codec_free = speex_codec_free;
    codec->headers = 1;
    format_ogg_attach_header (ogg_info, page);
    free (header);
    return codec;
}
Example #6
0
static int init(sh_audio_t *sh) {
  context_t *ctx = calloc(1, sizeof(context_t));
  const SpeexMode *spx_mode;
  const SpeexStereoState st_st = SPEEX_STEREO_STATE_INIT; // hack
  if (!sh->wf || sh->wf->cbSize < 80) {
    mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Missing extradata!\n");
    return 0;
  }
  ctx->hdr = speex_packet_to_header((char *)&sh->wf[1], sh->wf->cbSize);
  if (ctx->hdr->nb_channels != 1 && ctx->hdr->nb_channels != 2) {
    mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of channels (%i), "
            "assuming mono\n", ctx->hdr->nb_channels);
    ctx->hdr->nb_channels = 1;
  }
  if (ctx->hdr->frames_per_packet > MAX_FRAMES_PER_PACKET) {
    mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of frames per packet (%i), "
            "assuming 1\n", ctx->hdr->frames_per_packet);
    ctx->hdr->frames_per_packet = 1;
  }
  switch (ctx->hdr->mode) {
    case 0:
      spx_mode = &speex_nb_mode; break;
    case 1:
      spx_mode = &speex_wb_mode; break;
    case 2:
      spx_mode = &speex_uwb_mode; break;
    default:
      mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Unknown speex mode (%i)\n", ctx->hdr->mode);
      spx_mode = &speex_nb_mode;
  }
  ctx->dec_context = speex_decoder_init(spx_mode);
  speex_bits_init(&ctx->bits);
  memcpy(&ctx->stereo, &st_st, sizeof(ctx->stereo)); // hack part 2
  sh->channels = ctx->hdr->nb_channels;
  sh->samplerate = ctx->hdr->rate;
  sh->samplesize = 2;
  sh->sample_format = AF_FORMAT_S16_NE;
  sh->context = ctx;
  return 1;
}
Example #7
0
void SndSysSpeexSoundData::Initialize()
{
  ogg_sync_state oy;
  ogg_page og;
  ogg_packet op;
  ogg_stream_state os;

  // Process enough to get the header.
  ogg_sync_init(&oy);
  oy.data = m_DataStore.data;
  oy.storage = (int)m_DataStore.length;
  ogg_sync_wrote(&oy, (long)m_DataStore.length);
  ogg_sync_pageout(&oy, &og);
  ogg_stream_init(&os, ogg_page_serialno(&og));
  ogg_stream_pagein(&os, &og);
  ogg_stream_packetout(&os, &op);

  SpeexHeader* header = speex_packet_to_header((char*)op.packet, op.bytes);
  m_SoundFormat.Channels = header->nb_channels;
  m_SoundFormat.Freq = header->rate;

  // Is there a better way to do this?
  // Get number of packets (-1 as the second contains misc info).
  int count = -1;
  while(ogg_sync_pageout(&oy, &og)==1)
  {
    ogg_stream_pagein(&os, &og);
    count += ogg_page_packets(&og);
  }

  m_FrameCount = header->frames_per_packet * count;

  // Free memory.
  speex_header_free(header);
  ogg_stream_clear(&os);

  // No need to call this again.
  m_bInfoReady=true;
}
Example #8
0
/* -- speex functions -- */
int _shout_open_speex(ogg_codec_t *codec, ogg_page *page)
{
	speex_data_t *speex_data = calloc(1, sizeof(speex_data_t));
	ogg_packet packet;

	if (!speex_data)
		return SHOUTERR_MALLOC;

	ogg_stream_packetout(&codec->os, &packet);

	if (!(speex_data->sh = speex_packet_to_header(packet.packet,packet.bytes))) {
		free_speex_data(speex_data);
		
		return SHOUTERR_UNSUPPORTED;
	}

	codec->codec_data = speex_data;
	codec->read_page = read_speex_page;
	codec->free_data = free_speex_data;

	return SHOUTERR_SUCCESS;
}
Example #9
0
static int init(sh_audio_t *sh) {
  context_t *ctx = calloc(1, sizeof(context_t));
  const uint8_t *hdr = (const uint8_t *)(sh->wf + 1);
  const SpeexMode *spx_mode;
  const SpeexStereoState st_st = SPEEX_STEREO_STATE_INIT; // hack
  if (sh->wf && sh->wf->cbSize >= 80)
    ctx->hdr = speex_packet_to_header((char *)&sh->wf[1], sh->wf->cbSize);
  if (!ctx->hdr && sh->wf->cbSize == 0x72 && hdr[0] == 1 && hdr[1] == 0) {
    // speex.acm format: raw SpeexHeader dump
    ctx->hdr = calloc(1, sizeof(*ctx->hdr));
    hdr += 2;
    hdr += 8; // identifier string
    hdr += 20; // version string
    ctx->hdr->speex_version_id = read_le32(&hdr);
    ctx->hdr->header_size = read_le32(&hdr);
    ctx->hdr->rate = read_le32(&hdr);
    ctx->hdr->mode = read_le32(&hdr);
    ctx->hdr->mode_bitstream_version = read_le32(&hdr);
    ctx->hdr->nb_channels = read_le32(&hdr);
    ctx->hdr->bitrate = read_le32(&hdr);
    ctx->hdr->frame_size = read_le32(&hdr);
    ctx->hdr->vbr = read_le32(&hdr);
    ctx->hdr->frames_per_packet = read_le32(&hdr);
  }
  if (!ctx->hdr) {
    mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Invalid or missing extradata! Assuming defaults.\n");
    ctx->hdr = calloc(1, sizeof(*ctx->hdr));
    ctx->hdr->frames_per_packet = 1;
    ctx->hdr->mode = 0;
    if (sh->wf) {
      ctx->hdr->nb_channels = sh->wf->nChannels;
      ctx->hdr->rate = sh->wf->nSamplesPerSec;
      if (ctx->hdr->rate > 16000)
        ctx->hdr->mode = 2;
      else if (ctx->hdr->rate > 8000)
        ctx->hdr->mode = 1;
    }
  }
  if (ctx->hdr->nb_channels != 1 && ctx->hdr->nb_channels != 2) {
    mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of channels (%i), "
            "assuming mono\n", ctx->hdr->nb_channels);
    ctx->hdr->nb_channels = 1;
  }
  if (ctx->hdr->frames_per_packet > MAX_FRAMES_PER_PACKET) {
    mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of frames per packet (%i), "
            "assuming 1\n", ctx->hdr->frames_per_packet);
    ctx->hdr->frames_per_packet = 1;
  }
  switch (ctx->hdr->mode) {
    case 0:
      spx_mode = &speex_nb_mode; break;
    case 1:
      spx_mode = &speex_wb_mode; break;
    case 2:
      spx_mode = &speex_uwb_mode; break;
    default:
      mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Unknown speex mode (%i)\n", ctx->hdr->mode);
      spx_mode = &speex_nb_mode;
  }
  ctx->dec_context = speex_decoder_init(spx_mode);
  speex_bits_init(&ctx->bits);
  memcpy(&ctx->stereo, &st_st, sizeof(ctx->stereo)); // hack part 2
  sh->channels = ctx->hdr->nb_channels;
  sh->samplerate = ctx->hdr->rate;
  sh->samplesize = 2;
  sh->sample_format = AF_FORMAT_S16_NE;
  sh->context = ctx;
  return 1;
}
Example #10
0
File: speex.c Project: 0xheart0/vlc
/*****************************************************************************
 * ProcessInitialHeader: processes the inital Speex header packet.
 *****************************************************************************/
static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    void *p_state;
    SpeexHeader *p_header;
    const SpeexMode *p_mode;
    SpeexCallback callback;

    p_sys->p_header = p_header =
        speex_packet_to_header( (char *)p_oggpacket->packet,
                                p_oggpacket->bytes );
    if( !p_header )
    {
        msg_Err( p_dec, "cannot read Speex header" );
        return VLC_EGENERIC;
    }
    if( p_header->mode >= SPEEX_NB_MODES || p_header->mode < 0 )
    {
        msg_Err( p_dec, "mode number %d does not (yet/any longer) exist in "
                 "this version of libspeex.", p_header->mode );
        return VLC_EGENERIC;
    }

    p_mode = speex_mode_list[p_header->mode];
    if( p_mode == NULL )
        return VLC_EGENERIC;

    if( p_header->speex_version_id > 1 )
    {
        msg_Err( p_dec, "this file was encoded with Speex bit-stream "
                 "version %d which is not supported by this decoder.",
                 p_header->speex_version_id );
        return VLC_EGENERIC;
    }

    if( p_mode->bitstream_version < p_header->mode_bitstream_version )
    {
        msg_Err( p_dec, "file encoded with a newer version of Speex." );
        return VLC_EGENERIC;
    }
    if( p_mode->bitstream_version > p_header->mode_bitstream_version )
    {
        msg_Err( p_dec, "file encoded with an older version of Speex." );
        return VLC_EGENERIC;
    }

    msg_Dbg( p_dec, "Speex %d Hz audio using %s mode %s%s",
             p_header->rate, p_mode->modeName,
             ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo",
             p_header->vbr ? ", VBR)" : ")" );

    /* Take care of speex decoder init */
    speex_bits_init( &p_sys->bits );
    p_sys->p_state = p_state = speex_decoder_init( p_mode );
    if( !p_state )
    {
        msg_Err( p_dec, "decoder initialization failed" );
        return VLC_EGENERIC;
    }

    if( p_header->nb_channels == 2 )
    {
        SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
        p_sys->stereo = stereo;
        callback.callback_id = SPEEX_INBAND_STEREO;
        callback.func = speex_std_stereo_request_handler;
        callback.data = &p_sys->stereo;
        speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback );
    }
    if( p_header->nb_channels <= 0 ||
        p_header->nb_channels > 5 )
    {
        msg_Err( p_dec, "invalid number of channels (not between 1 and 5): %i",
                 p_header->nb_channels );
        return VLC_EGENERIC;
    }

    /* Setup the format */
    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels =
            pi_channels_maps[p_header->nb_channels];
    p_dec->fmt_out.audio.i_channels = p_header->nb_channels;
    p_dec->fmt_out.audio.i_rate = p_header->rate;

    date_Init( &p_sys->end_date, p_header->rate, 1 );

    return VLC_SUCCESS;
}
Example #11
0
static void *process_header(ogg_packet *op, spx_int32_t enh_enabled, spx_int32_t *frame_size, int *granule_frame_size, spx_int32_t *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo, int *extra_headers, int quiet)
{
   void *st;
   const SpeexMode *mode;
   SpeexHeader *header;
   int modeID;
   SpeexCallback callback;
      
   header = speex_packet_to_header((char*)op->packet, op->bytes);
   if (!header)
   {
      WriteDebugLog("Cannot read header");
      //fprintf (stderr, "Cannot read header\n");
      return NULL;
   }
   if (header->mode >= SPEEX_NB_MODES || header->mode<0)
   {
       WriteDebugLog("Mode number %d does not (yet/any longer) exist in this version");
      //fprintf (stderr, "Mode number %d does not (yet/any longer) exist in this version\n", 
      //         header->mode);
      free(header);
      return NULL;
   }
      
   modeID = header->mode;
   if (forceMode!=-1)
      modeID = forceMode;

   mode = speex_lib_get_mode (modeID);
   
   if (header->speex_version_id > 1)
   {
       char Error[256] = {0};
       sprintf(Error,"This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id);
       WriteDebugLog(Error);
      //fprintf (stderr, "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id);
      free(header);
      return NULL;
   }

   if (mode->bitstream_version < header->mode_bitstream_version)
   {
      WriteDebugLog("The file was encoded with a newer version of Speex. You need to upgrade in order to play it.");
      //fprintf (stderr, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n");
      free(header);
      return NULL;
   }
   if (mode->bitstream_version > header->mode_bitstream_version) 
   {
      WriteDebugLog("The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.");
      //fprintf (stderr, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n");
      free(header);
      return NULL;
   }
   
   st = speex_decoder_init(mode);
   if (!st)
   {
      WriteDebugLog("Decoder initialization failed.");
      //fprintf (stderr, "Decoder initialization failed.\n");
      free(header);
      return NULL;
   }
   speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
   speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);
   *granule_frame_size = *frame_size;

   if (!*rate)
      *rate = header->rate;
   /* Adjust rate if --force-* options are used */
   if (forceMode!=-1)
   {
      if (header->mode < forceMode)
      {
         *rate <<= (forceMode - header->mode);
         *granule_frame_size >>= (forceMode - header->mode);
      }
      if (header->mode > forceMode)
      {
         *rate >>= (header->mode - forceMode);
         *granule_frame_size <<= (header->mode - forceMode);
      }
static GstFlowReturn
gst_speex_dec_parse_header (GstSpeexDec * dec, GstBuffer * buf)
{
  GstCaps *caps;

  /* get the header */
  dec->header = speex_packet_to_header ((char *) GST_BUFFER_DATA (buf),
      GST_BUFFER_SIZE (buf));

  if (!dec->header)
    goto no_header;

  if (dec->header->mode >= SPEEX_NB_MODES || dec->header->mode < 0)
    goto mode_too_old;

  dec->mode = speex_lib_get_mode (dec->header->mode);

  /* initialize the decoder */
  dec->state = speex_decoder_init (dec->mode);
  if (!dec->state)
    goto init_failed;

  speex_decoder_ctl (dec->state, SPEEX_SET_ENH, &dec->enh);
  speex_decoder_ctl (dec->state, SPEEX_GET_FRAME_SIZE, &dec->frame_size);

  if (dec->header->nb_channels != 1) {
    dec->stereo = speex_stereo_state_init ();
    dec->callback.callback_id = SPEEX_INBAND_STEREO;
    dec->callback.func = speex_std_stereo_request_handler;
    dec->callback.data = dec->stereo;
    speex_decoder_ctl (dec->state, SPEEX_SET_HANDLER, &dec->callback);
  }

  speex_decoder_ctl (dec->state, SPEEX_SET_SAMPLING_RATE, &dec->header->rate);

  dec->frame_duration = gst_util_uint64_scale_int (dec->frame_size,
      GST_SECOND, dec->header->rate);

  speex_bits_init (&dec->bits);

  /* set caps */
  caps = gst_caps_new_simple ("audio/x-raw-int",
      "rate", G_TYPE_INT, dec->header->rate,
      "channels", G_TYPE_INT, dec->header->nb_channels,
      "signed", G_TYPE_BOOLEAN, TRUE,
      "endianness", G_TYPE_INT, G_BYTE_ORDER,
      "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, NULL);

  if (!gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps))
    goto nego_failed;

  gst_caps_unref (caps);
  return GST_FLOW_OK;

  /* ERRORS */
no_header:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't read header"));
    return GST_FLOW_ERROR;
  }
mode_too_old:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL),
        ("Mode number %d does not (yet/any longer) exist in this version",
            dec->header->mode));
    return GST_FLOW_ERROR;
  }
init_failed:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't initialize decoder"));
    return GST_FLOW_ERROR;
  }
nego_failed:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't negotiate format"));
    gst_caps_unref (caps);
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
Example #13
0
static GstFlowReturn
gst_speex_dec_parse_header (GstSpeexDec * dec, GstBuffer * buf)
{
  SpeexHeader *header;
  GstMapInfo map;
  GstAudioInfo info;
  static const GstAudioChannelPosition chan_pos[2][2] = {
    {GST_AUDIO_CHANNEL_POSITION_MONO},
    {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
  };

  /* get the header */
  gst_buffer_map (buf, &map, GST_MAP_READ);
  header = speex_packet_to_header ((gchar *) map.data, map.size);
  gst_buffer_unmap (buf, &map);

  if (!header)
    goto no_header;

  if (dec->header) {
    GST_DEBUG_OBJECT (dec, "Replacing speex-header, resetting state");
    gst_speex_dec_reset (dec);
  }
  dec->header = header;

  if (dec->header->mode >= SPEEX_NB_MODES || dec->header->mode < 0)
    goto mode_too_old;

  dec->mode = speex_lib_get_mode (dec->header->mode);

  /* initialize the decoder */
  dec->state = speex_decoder_init (dec->mode);
  if (!dec->state)
    goto init_failed;

  speex_decoder_ctl (dec->state, SPEEX_SET_ENH, &dec->enh);
  speex_decoder_ctl (dec->state, SPEEX_GET_FRAME_SIZE, &dec->frame_size);

  if (dec->header->nb_channels != 1) {
    dec->stereo = speex_stereo_state_init ();
    dec->callback.callback_id = SPEEX_INBAND_STEREO;
    dec->callback.func = speex_std_stereo_request_handler;
    dec->callback.data = dec->stereo;
    speex_decoder_ctl (dec->state, SPEEX_SET_HANDLER, &dec->callback);
  }

  speex_decoder_ctl (dec->state, SPEEX_SET_SAMPLING_RATE, &dec->header->rate);

  dec->frame_duration = gst_util_uint64_scale_int (dec->frame_size,
      GST_SECOND, dec->header->rate);

  speex_bits_init (&dec->bits);

  /* set caps */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info,
      GST_AUDIO_FORMAT_S16,
      dec->header->rate,
      dec->header->nb_channels, chan_pos[dec->header->nb_channels - 1]);

  if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info))
    goto nego_failed;

  return GST_FLOW_OK;

  /* ERRORS */
no_header:
  {
    GST_INFO_OBJECT (dec, "couldn't read header");
    return GST_FLOW_NO_HEADER;
  }
mode_too_old:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL),
        ("Mode number %d does not (yet/any longer) exist in this version",
            dec->header->mode));
    return GST_FLOW_ERROR;
  }
init_failed:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't initialize decoder"));
    return GST_FLOW_ERROR;
  }
nego_failed:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't negotiate format"));
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
Example #14
0
static void *
spx_header_read (SF_PRIVATE * psf, ogg_packet *op, spx_int32_t enh_enabled, int force_mode)
{	SPX_PRIVATE* spx = psf->codec_data ;
	void *st ;
	const SpeexMode *mode ;
	SpeexHeader *tmp_header ;
	int modeID ;
	SpeexCallback callback ;

	tmp_header = speex_packet_to_header ((char*) op->packet, op->bytes) ;
	if (tmp_header == NULL)
	{	psf_log_printf (psf, "Cannot read Speex header\n") ;
		return NULL ;
		} ;

	memcpy (&spx->header, tmp_header, sizeof (spx->header)) ;
	free (tmp_header) ;
	tmp_header = NULL ;

	if (spx->header.mode >= SPEEX_NB_MODES || spx->header.mode < 0)
	{	psf_log_printf (psf, "Mode number %d does not (yet/any longer) exist in this version\n", spx->header.mode) ;
		return NULL ;
		} ;

	modeID = spx->header.mode ;
	if (force_mode != -1)
		modeID = force_mode ;

	mode = speex_lib_get_mode (modeID) ;

	if (spx->header.speex_version_id > 1)
	{	psf_log_printf (psf, "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", spx->header.speex_version_id) ;
		return NULL ;
		} ;

	if (mode->bitstream_version < spx->header.mode_bitstream_version)
	{	psf_log_printf (psf, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n") ;
		return NULL ;
		} ;

	if (mode->bitstream_version > spx->header.mode_bitstream_version)
	{	psf_log_printf (psf, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n") ;
		return NULL ;
		} ;

	st = speex_decoder_init (mode) ;
	if (!st)
	{	psf_log_printf (psf, "Decoder initialization failed.\n") ;
		return NULL ;
		} ;

	speex_decoder_ctl (st, SPEEX_SET_ENH, &enh_enabled) ;
	speex_decoder_ctl (st, SPEEX_GET_FRAME_SIZE, &spx->frame_size) ;
	spx->granule_frame_size = spx->frame_size ;

	if (!psf->sf.samplerate)
		psf->sf.samplerate = spx->header.rate ;
	/* Adjust rate if --force-* options are used */
	if (force_mode != -1)
	{	if (spx->header.mode < force_mode)
		{	psf->sf.samplerate <<= (force_mode - spx->header.mode) ;
			spx->granule_frame_size >>= (force_mode - spx->header.mode) ;
			} ;
		if (spx->header.mode > force_mode)
		{	psf->sf.samplerate >>= (spx->header.mode - force_mode) ;
			spx->granule_frame_size <<= (spx->header.mode - force_mode) ;
			} ;
Example #15
0
bool OggSpeexDecoder::Open(CFErrorRef *error)
{
	if(IsOpen()) {
		LOGGER_WARNING("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Open() called on an AudioDecoder that is already open");		
		return true;
	}

	// Ensure the input source is open
	if(!mInputSource->IsOpen() && !mInputSource->Open(error))
		return false;

	// Initialize Ogg data struct
	ogg_sync_init(&mOggSyncState);

	// Get the ogg buffer for writing
	char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);
	
	// Read bitstream from input file
	ssize_t bytesRead = GetInputSource()->Read(data, READ_SIZE_BYTES);
	if(-1 == bytesRead) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” could not be read."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Read error"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("Unable to read from the input file."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderInputOutputError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Tell the sync layer how many bytes were written to its internal buffer
	int result = ogg_sync_wrote(&mOggSyncState, bytesRead);
	if(-1 == result) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Turn the data we wrote into an ogg page
	result = ogg_sync_pageout(&mOggSyncState, &mOggPage);
	if(1 != result) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Initialize the stream and grab the serial number
	ogg_stream_init(&mOggStreamState, ogg_page_serialno(&mOggPage));
	
	// Get the first Ogg page
	result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
	if(0 != result) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Get the first packet (should be the header) from the page
	ogg_packet op;
	result = ogg_stream_packetout(&mOggStreamState, &op);
	if(1 != result) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	if(op.bytes >= 5 && !memcmp(op.packet, "Speex", 5))
		mSpeexSerialNumber = mOggStreamState.serialno;

	++mOggPacketCount;
	
	// Convert the packet to the Speex header
	SpeexHeader *header = speex_packet_to_header((char *)op.packet, static_cast<int>(op.bytes));
	if(NULL == header) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg Speex file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not an Ogg Speex file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotRecognizedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	else if(SPEEX_NB_MODES <= header->mode) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The Speex mode in the file “%@” is not supported."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file mode"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("This file may have been encoded with a newer version of Speex."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotSupportedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		speex_header_free(header), header = NULL;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	const SpeexMode *mode = speex_lib_get_mode(header->mode);
	if(mode->bitstream_version != header->mode_bitstream_version) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The Speex version in the file “%@” is not supported."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderFileFormatNotSupportedError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		speex_header_free(header), header = NULL;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Initialize the decoder
	mSpeexDecoder = speex_decoder_init(mode);
	if(NULL== mSpeexDecoder) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   0,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 CFCopyLocalizedString(CFSTR("Unable to initialize the Speex decoder."), ""));
			
//			CFDictionarySetValue(errorDictionary, 
//								 kCFErrorLocalizedFailureReasonKey, 
//								 CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), ""));
			
//			CFDictionarySetValue(errorDictionary, 
//								 kCFErrorLocalizedRecoverySuggestionKey, 
//								 CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), ""));
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderInputOutputError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		speex_header_free(header), header = NULL;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_SAMPLING_RATE, &header->rate);
	
	mSpeexFramesPerOggPacket = (0 == header->frames_per_packet ? 1 : header->frames_per_packet);
	mExtraSpeexHeaderCount = header->extra_headers;

	// Initialize the speex bit-packing data structure
	speex_bits_init(&mSpeexBits);
	
	// Initialize the stereo mode
	mSpeexStereoState = speex_stereo_state_init();
	
	if(2 == header->nb_channels) {
		SpeexCallback callback;
		callback.callback_id = SPEEX_INBAND_STEREO;
		callback.func = speex_std_stereo_request_handler;
		callback.data = mSpeexStereoState;
		speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_HANDLER, &callback);
	}
	
	// Canonical Core Audio format
	mFormat.mFormatID			= kAudioFormatLinearPCM;
	mFormat.mFormatFlags		= kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
	
	mFormat.mBitsPerChannel		= 8 * sizeof(float);
	mFormat.mSampleRate			= header->rate;
	mFormat.mChannelsPerFrame	= header->nb_channels;
	
	mFormat.mBytesPerPacket		= (mFormat.mBitsPerChannel / 8);
	mFormat.mFramesPerPacket	= 1;
	mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;
	
	mFormat.mReserved			= 0;
	
	// Set up the source format
	mSourceFormat.mFormatID				= 'SPEE';
	
	mSourceFormat.mSampleRate			= header->rate;
	mSourceFormat.mChannelsPerFrame		= header->nb_channels;
	
	switch(header->nb_channels) {
		case 1:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);			break;
		case 2:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);			break;
	}
	
	speex_header_free(header), header = NULL;

	// Allocate the buffer list
	spx_int32_t speexFrameSize = 0;
	speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);
	
	mBufferList = AllocateABL(mFormat, speexFrameSize);
	if(NULL == mBufferList) {
		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL);

		speex_header_free(header), header = NULL;
		speex_stereo_state_destroy(mSpeexStereoState), mSpeexStereoState = NULL;
		speex_decoder_destroy(mSpeexDecoder), mSpeexDecoder = NULL;
		speex_bits_destroy(&mSpeexBits);

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i)
		mBufferList->mBuffers[i].mDataByteSize = 0;

	mIsOpen = true;
	return true;
}
Example #16
0
static gboolean
xmms_speex_init (xmms_xform_t *xform)
{
	gint pe;

	xmms_config_property_t *val;
	xmms_speex_data_t *data;
	xmms_error_t error;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_speex_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	ogg_sync_init (&data->sync_state);
	speex_bits_init (&data->speex_bits);

	/* Find the speex header */

	while (42) {
		gint ret;

		data->ogg_data = ogg_sync_buffer (&data->sync_state, 1024);
		ret = xmms_xform_read (xform, data->ogg_data, 1024, &error);
		ogg_sync_wrote (&data->sync_state, ret);

		if (ret <= 0) {
			return FALSE;
		}

		if (ogg_sync_pageout (&data->sync_state, &data->ogg_page) == 1) {
			break;
		}
	}

	ogg_stream_init (&data->stream_state, ogg_page_serialno (&data->ogg_page));

	if (ogg_stream_pagein (&data->stream_state, &data->ogg_page) < 0) {
		return FALSE;
	}

	if (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) != 1) {
		return FALSE;
	}

	data->speexheader = speex_packet_to_header ((char *)data->ogg_packet.packet,
	                                            data->ogg_packet.bytes);
	data->speex_state = speex_decoder_init (speex_mode_list[data->speexheader->mode]);

	val = xmms_xform_config_lookup (xform, "perceptual_enhancer");
	pe = xmms_config_property_get_int (val);
	speex_decoder_ctl (data->speex_state, SPEEX_SET_ENH, &pe);

	ogg_sync_pageout (&data->sync_state, &data->ogg_page);
	ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	ogg_stream_packetout (&data->stream_state, &data->ogg_packet);

	data->samples_buf = g_new (gint16,
	                           data->speexheader->frames_per_packet *
	                           data->speexheader->frame_size *
	                           data->speexheader->nb_channels);
	data->samples_start = data->samples_buf;
	data->samples_count = 0;

	xmms_speex_read_metadata (xform, data);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S16,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->speexheader->nb_channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->speexheader->rate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Example #17
0
static int
read_ogg_packet(OGGZ * oggz, oggz_packet * zp, long serialno, void * user_data) {

	ogg_packet * op = &zp->op;
	decoder_t * dec = (decoder_t *)user_data;
	speex_pdata_t * pd = (speex_pdata_t *)dec->pdata;

	if (pd->exploring && (pd->packetno == 0)) {
		/* Speex header */

		int i;
                int ptr = 0;
                char speex_string[9];
		int enh = 1;

                SpeexHeader * header;


                for (i = 0; i < 8; i++) {
                        speex_string[i] = op->packet[ptr++];
                }
                speex_string[i] = '\0';

                if (strcmp(speex_string, "Speex   ") != 0) {
			printf("read_ogg_packet(): Not a Speex stream\n");
                        pd->error = 1;
			return 0;
                }

                speex_bits_init(&(pd->bits));

                header = speex_packet_to_header((char *)op->packet, op->bytes);
                if (!header) {
                        printf("Cannot read Speex header\n");
			pd->error = 1;
                        return 0;
                }

                pd->mode = speex_mode_list[header->mode];

                if (pd->mode->bitstream_version > header->mode_bitstream_version) {
                        fprintf(stderr, "Unknown bitstream version! The file was encoded with an older version of Speex.\n"
                                "You need to downgrade Speex in order to play it.\n");
			pd->error = 1;
                        return 0;
                }

                if (pd->mode->bitstream_version < header->mode_bitstream_version) {
                        fprintf(stderr, "Unknown bitstream version! The file was encoded with a newer version of Speex.\n"
                                "You need to upgrade Speex in order to play it.\n");
			pd->error = 1;
                        return 0;
                }

		pd->sample_rate = header->rate;
		pd->channels = header->nb_channels;
		pd->vbr = header->vbr;

                if (header->frames_per_packet != 0)
                        pd->nframes = header->frames_per_packet;

                pd->decoder = speex_decoder_init(pd->mode);
                speex_decoder_ctl(pd->decoder, SPEEX_GET_FRAME_SIZE, &(pd->frame_size));
                speex_decoder_ctl(pd->decoder, SPEEX_SET_ENH, &enh);

	} else if (pd->packetno >= 2) {

		int j;
		float output_frame[SPEEX_BUFSIZE];

		pd->granulepos = op->granulepos;

		if (!pd->exploring) {
			speex_bits_read_from(&(pd->bits), (char *)op->packet, op->bytes);
			
			for (j = 0; j < pd->nframes; j++) {
				
				int k;
				
				speex_decode(pd->decoder, &(pd->bits), output_frame);
				
				for (k = 0; k < pd->frame_size * pd->channels; k++) {
					output_frame[k] /= 32768.0f;
					if (output_frame[k] > 1.0f) {
						output_frame[k] = 1.0f;
					} else if (output_frame[k] < -1.0f) {
						output_frame[k] = -1.0f;
					}
				}
				
				rb_write(pd->rb, (char *)output_frame,
						      pd->channels * pd->frame_size * sample_size);
			}
		}
	}
	
	++pd->packetno;
	return 0;
}
bool SFB::Audio::OggSpeexDecoder::_Open(CFErrorRef *error)
{
	// Initialize Ogg data struct
	ogg_sync_init(&mOggSyncState);

	// Get the ogg buffer for writing
	char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);

	// Read bitstream from input file
	ssize_t bytesRead = (ssize_t)GetInputSource().Read(data, READ_SIZE_BYTES);
	if(-1 == bytesRead) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be read."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Read error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("Unable to read from the input file."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Tell the sync layer how many bytes were written to its internal buffer
	int result = ogg_sync_wrote(&mOggSyncState, bytesRead);
	if(-1 == result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Turn the data we wrote into an ogg page
	result = ogg_sync_pageout(&mOggSyncState, &mOggPage);
	if(1 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Initialize the stream and grab the serial number
	ogg_stream_init(&mOggStreamState, ogg_page_serialno(&mOggPage));

	// Get the first Ogg page
	result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
	if(0 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Get the first packet (should be the header) from the page
	ogg_packet op;
	result = ogg_stream_packetout(&mOggStreamState, &op);
	if(1 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	if(op.bytes >= 5 && !memcmp(op.packet, "Speex", 5))
		mSpeexSerialNumber = mOggStreamState.serialno;

	++mOggPacketCount;

	// Convert the packet to the Speex header
	SpeexHeader *header = speex_packet_to_header((char *)op.packet, (int)op.bytes);
	if(nullptr == header) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg Speex file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg Speex file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotRecognizedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	else if(SPEEX_NB_MODES <= header->mode) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The Speex mode in the file “%@” is not supported."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file mode"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("This file may have been encoded with a newer version of Speex."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotSupportedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		speex_header_free(header);
		header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	const SpeexMode *mode = speex_lib_get_mode(header->mode);
	if(mode->bitstream_version != header->mode_bitstream_version) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The Speex version in the file “%@” is not supported."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotSupportedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		speex_header_free(header);
		header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Initialize the decoder
	mSpeexDecoder = speex_decoder_init(mode);
	if(nullptr== mSpeexDecoder) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("Unable to initialize the Speex decoder."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Error initializing Speex decoder"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("An unknown error occurred."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		speex_header_free(header);
		header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_SAMPLING_RATE, &header->rate);

	mSpeexFramesPerOggPacket = (0 == header->frames_per_packet ? 1 : header->frames_per_packet);
	mExtraSpeexHeaderCount = (UInt32)header->extra_headers;

	// Initialize the speex bit-packing data structure
	speex_bits_init(&mSpeexBits);

	// Initialize the stereo mode
	mSpeexStereoState = speex_stereo_state_init();

	if(2 == header->nb_channels) {
		SpeexCallback callback;
		callback.callback_id = SPEEX_INBAND_STEREO;
		callback.func = speex_std_stereo_request_handler;
		callback.data = mSpeexStereoState;
		speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_HANDLER, &callback);
	}

	// Canonical Core Audio format
	mFormat.mFormatID			= kAudioFormatLinearPCM;
	mFormat.mFormatFlags		= kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;

	mFormat.mBitsPerChannel		= 8 * sizeof(float);
	mFormat.mSampleRate			= header->rate;
	mFormat.mChannelsPerFrame	= (UInt32)header->nb_channels;

	mFormat.mBytesPerPacket		= (mFormat.mBitsPerChannel / 8);
	mFormat.mFramesPerPacket	= 1;
	mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;

	mFormat.mReserved			= 0;

	// Set up the source format
	mSourceFormat.mFormatID				= 'SPEE';

	mSourceFormat.mSampleRate			= header->rate;
	mSourceFormat.mChannelsPerFrame		= (UInt32)header->nb_channels;

	switch(header->nb_channels) {
		case 1:		mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);		break;
		case 2:		mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);	break;
	}

	speex_header_free(header);
	header = nullptr;

	// Allocate the buffer list
	spx_int32_t speexFrameSize = 0;
	speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);

	if(!mBufferList.Allocate(mFormat, (UInt32)speexFrameSize)) {
		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, nullptr);

		speex_stereo_state_destroy(mSpeexStereoState);
		mSpeexStereoState = nullptr;
		speex_decoder_destroy(mSpeexDecoder);
		mSpeexDecoder = nullptr;
		speex_bits_destroy(&mSpeexBits);

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i)
		mBufferList->mBuffers[i].mDataByteSize = 0;

	return true;
}
Example #19
0
static av_cold int libspeex_decode_init(AVCodecContext *avctx)
{
    LibSpeexContext *s = avctx->priv_data;
    const SpeexMode *mode;
    SpeexHeader *header = NULL;
    int spx_mode;

    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
    if (avctx->extradata && avctx->extradata_size >= 80) {
        header = speex_packet_to_header(avctx->extradata,
                                        avctx->extradata_size);
        if (!header)
            av_log(avctx, AV_LOG_WARNING, "Invalid Speex header\n");
    }
    if (avctx->codec_tag == MKTAG('S', 'P', 'X', 'N')) {
        if (!avctx->extradata || avctx->extradata && avctx->extradata_size < 47) {
            av_log(avctx, AV_LOG_ERROR, "Missing or invalid extradata.\n");
            return AVERROR_INVALIDDATA;
        }
        if (avctx->extradata[37] != 10) {
            av_log(avctx, AV_LOG_ERROR, "Unsupported quality mode.\n");
            return AVERROR_PATCHWELCOME;
        }
        spx_mode           = 0;
    } else if (header) {
        avctx->sample_rate = header->rate;
        avctx->channels    = header->nb_channels;
        spx_mode           = header->mode;
        speex_header_free(header);
    } else {
        switch (avctx->sample_rate) {
        case 8000:  spx_mode = 0; break;
        case 16000: spx_mode = 1; break;
        case 32000: spx_mode = 2; break;
        default:
            /* libspeex can handle any mode if initialized as ultra-wideband */
            av_log(avctx, AV_LOG_WARNING, "Invalid sample rate: %d\n"
                                          "Decoding as 32kHz ultra-wideband\n",
                                          avctx->sample_rate);
            spx_mode = 2;
        }
    }

    mode = speex_lib_get_mode(spx_mode);
    if (!mode) {
        av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", spx_mode);
        return AVERROR_INVALIDDATA;
    }
    s->frame_size      =  160 << spx_mode;
    if (!avctx->sample_rate)
        avctx->sample_rate = 8000 << spx_mode;

    if (avctx->channels < 1 || avctx->channels > 2) {
        /* libspeex can handle mono or stereo if initialized as stereo */
        av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n"
                                    "Decoding as stereo.\n", avctx->channels);
        avctx->channels = 2;
    }
    avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO :
                                                   AV_CH_LAYOUT_MONO;

    speex_bits_init(&s->bits);
    s->dec_state = speex_decoder_init(mode);
    if (!s->dec_state) {
        av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
        return -1;
    }

    if (avctx->channels == 2) {
        SpeexCallback callback;
        callback.callback_id = SPEEX_INBAND_STEREO;
        callback.func = speex_std_stereo_request_handler;
        callback.data = &s->stereo;
        s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
        speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
    }

    return 0;
}
Example #20
0
void SndSysSpeexSoundStream::AdvancePosition(size_t frame_delta)
{
  if (m_bPaused || m_bPlaybackReadComplete || frame_delta==0)
    return;

  // Figure out how many bytes we need to fill for this advancement
  size_t needed_bytes = frame_delta * (m_RenderFormat.Bits/8) * m_RenderFormat.Channels;

  // If we need more space than is available in the whole cyclic buffer, then we already underbuffered, reduce to just 1 cycle full
  if ((size_t)needed_bytes > m_pCyclicBuffer->GetLength())
    needed_bytes=(size_t)(m_pCyclicBuffer->GetLength() & 0x7FFFFFFF);

  // Free space in the cyclic buffer if necessary
  if ((size_t)needed_bytes > m_pCyclicBuffer->GetFreeBytes())
    m_pCyclicBuffer->AdvanceStartValue(needed_bytes - (size_t)(m_pCyclicBuffer->GetFreeBytes() & 0x7FFFFFFF));

  // Fill in leftover decoded data if needed
  if (m_PreparedDataBufferUsage > 0)
    needed_bytes-=CopyBufferBytes(needed_bytes);

  while (needed_bytes > 0)
  {
    if(newPage)
    {
      if(ogg_sync_pageout(&oy, &og) != 1)
      {
        // Mark as complete if not looping.
        if (!m_bLooping)
        {
          m_bPlaybackReadComplete = true;
        }

        // Reset stream.
        ResetPosition();

        return;
      }

      if (!stream_init)
      {
        ogg_stream_init(&os, ogg_page_serialno(&og));
        stream_init = true;
      }

      if (ogg_page_serialno(&og) != os.serialno)
      {
        ogg_stream_reset_serialno(&os, ogg_page_serialno(&og));
      }

      ogg_stream_pagein(&os, &og);
      newPage = false;
    }

    if(ogg_stream_packetout(&os, &op) != 1)
    {
      newPage = true;
      continue;
    }

    // First packets contain header data.
    if(packet_count == 0)
    {
      if(header)
      {
        speex_header_free(header);
      }

      header = speex_packet_to_header((char*)op.packet, op.bytes);
      // const_cast for version compatibility.
      SpeexMode* mode = const_cast<SpeexMode*>(speex_lib_get_mode (header->mode));
      state = speex_decoder_init(mode);
      speex_decoder_ctl(state, SPEEX_SET_SAMPLING_RATE, &header->rate);

      m_OutputFrequency=m_NewOutputFrequency;

      // Create the pcm sample converter if it's not yet created
      if (m_pPCMConverter == 0)
        m_pPCMConverter = new PCMSampleConverter (
        m_RenderFormat.Channels, m_RenderFormat.Bits,
        m_RenderFormat.Freq);

      // Calculate the size of one source sample
      int source_sample_size = m_RenderFormat.Channels * m_RenderFormat.Bits;

      // Calculate the needed buffer size for this conversion
      int needed_buffer = (m_pPCMConverter->GetRequiredOutputBufferMultiple (
        m_RenderFormat.Channels, m_RenderFormat.Bits, m_OutputFrequency) * 
        (4096 + source_sample_size))/1024;

      // Allocate a new buffer.
      if (m_PreparedDataBufferSize < needed_buffer)
      {
        delete[] m_pPreparedDataBuffer;
        m_pPreparedDataBuffer = new char[needed_buffer];
        m_PreparedDataBufferSize=needed_buffer;
      }
    }

    if(packet_count++ < uint(2+header->extra_headers))
    {
      continue;
    }

    // Read and decode.
    speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
    speex_decode_int(state, &bits, (int16*)m_pPreparedDataBuffer);

    // Frame size is in shorts.
    speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &m_PreparedDataBufferUsage);
    m_PreparedDataBufferUsage *= sizeof(short);

    if (m_PreparedDataBufferUsage > 0)
      needed_bytes -= CopyBufferBytes (needed_bytes);
  }
}
Example #21
0
static void *process_header(spx_ogg_packet *op,
                            int enh_enabled,
                            int *frame_size,
                            int *rate,
                            int *nframes,
                            int *channels,
                            SpeexStereoState *stereo,
                            int *extra_headers
                           )
{
    void *st;
    const SpeexMode *mode;
    SpeexHeader *header;
    int modeID;
    SpeexCallback callback;

    header = speex_packet_to_header((char*)op->packet, op->bytes);

    if (!header){
        DEBUGF ("Cannot read header\n");
        return NULL;
    }

    if (header->mode >= SPEEX_NB_MODES){
        DEBUGF ("Mode does not exist\n");
        return NULL;
    }

    modeID = header->mode;

    mode = speex_lib_get_mode(modeID);

    if (header->speex_version_id > 1) {
        DEBUGF("Undecodeable bitstream");
        return NULL;
    }

    if (mode->bitstream_version < header->mode_bitstream_version){
        DEBUGF("Undecodeable bitstream, newer bitstream");
        return NULL;
    }

    if (mode->bitstream_version > header->mode_bitstream_version){
        DEBUGF("Too old bitstream");
        return NULL;
    }
   
    st = speex_decoder_init(mode);
    if (!st){
        DEBUGF("Decoder init failed");
        return NULL;
    }
    speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
    speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);

    if (header->nb_channels!=1){
        callback.callback_id = SPEEX_INBAND_STEREO;
        callback.func = speex_std_stereo_request_handler;
        callback.data = stereo;
        speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback);
    }
    *channels = header->nb_channels;

    if (!*rate)
        *rate = header->rate;

    speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, rate);

    *nframes = header->frames_per_packet;

    *extra_headers = header->extra_headers;

    return st;
}
Example #22
0
void *AudioStreamPlaybackSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) {

	SpeexHeader *header;
	int modeID;

	header = speex_packet_to_header((char *)op->packet, op->bytes);
	if (!header) {
		OS::get_singleton()->printerr("Cannot read header\n");
		return NULL;
	}
	if (header->mode >= SPEEX_NB_MODES) {
		OS::get_singleton()->printerr("Mode number %d does not (yet/any longer) exist in this version\n",
				header->mode);
		return NULL;
	}

	modeID = header->mode;

	const SpeexMode *mode = speex_lib_get_mode(modeID);

	if (header->speex_version_id > 1) {
		OS::get_singleton()->printerr("This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id);
		return NULL;
	}

	if (mode->bitstream_version < header->mode_bitstream_version) {
		OS::get_singleton()->printerr("The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n");
		return NULL;
	}
	if (mode->bitstream_version > header->mode_bitstream_version) {
		OS::get_singleton()->printerr("The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n");
		return NULL;
	}

	void *state = speex_decoder_init(mode);
	if (!state) {
		OS::get_singleton()->printerr("Decoder initialization failed.\n");
		return NULL;
	}
	//speex_decoder_ctl(state, SPEEX_SET_ENH, &enh_enabled);
	speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, frame_size);

	if (!*rate)
		*rate = header->rate;

	speex_decoder_ctl(state, SPEEX_SET_SAMPLING_RATE, rate);

	*nframes = header->frames_per_packet;

	*channels = header->nb_channels;

	if (*channels != 1) {
		OS::get_singleton()->printerr("Only MONO speex streams supported\n");
		return NULL;
	}

	*extra_headers = header->extra_headers;

	speex_free(header);
	return state;
}