X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=spx_common.c;fp=spx_common.c;h=ce01e23abd2c90aca37819148b735a4a26d14e2b;hp=0000000000000000000000000000000000000000;hb=90560de0d7e4d825772270f9ac7cbefbb38aad97;hpb=063328d833daa7e06589645e05d4d2e02f55e911 diff --git a/spx_common.c b/spx_common.c new file mode 100644 index 00000000..ce01e23a --- /dev/null +++ b/spx_common.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2002-2006 Jean-Marc Valin + * Copyright (C) 2010 Andre Noll + * + * Licensed under the GPL v2. For licencing details see COPYING. + */ + +/** + * \file spx_common.c Functions used by the speex decoder and the speex audio + * format handler. + */ + +/* This file is based on speexdec.c, by Jean-Marc Valin, see below. */ + +/* Copyright (C) 2002-2006 Jean-Marc Valin + File: speexdec.c + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include +#include + +#include "para.h" +#include "error.h" +#include "spx.h" + +/** + * Wrapper for speex_decoder_ctl(). + * + * \param state Decoder state. + * \param request ioctl-type request. + * \param ptr Value-result pointer. + * + * \return Standard. + */ +int spx_ctl(void *state, int request, void *ptr) +{ + int ret = speex_decoder_ctl(state, request, ptr); + + if (ret == 0) /* success */ + return 1; + if (ret == -1) + return -E_SPX_CTL_BAD_RQ; + return -E_SPX_CTL_INVAL; +} + +/** + * Obtain information about a speex file from an ogg packet. + * + * \param packet Start of the ogg packet. + * \param bytes Length of the ogg packet. + * \param shi Result pointer. + * + * \return Standard. + */ +int spx_process_header(unsigned char *packet, long bytes, + struct spx_header_info *shi) +{ + int ret; + spx_int32_t enh_enabled = 1; + SpeexHeader *h = speex_packet_to_header((char *)packet, bytes); + + if (!h) + return -E_SPX_HEADER; + ret = -E_SPX_HEADER_MODE; + if (h->mode >= SPEEX_NB_MODES || h->mode < 0) + goto out; + shi->mode = speex_lib_get_mode(h->mode); + + ret = -E_SPX_VERSION; + if (h->speex_version_id > 1) + goto out; + if (shi->mode->bitstream_version < h->mode_bitstream_version) + goto out; + if (shi->mode->bitstream_version > h->mode_bitstream_version) + goto out; + + ret = -E_SPX_DECODER_INIT; + shi->state = speex_decoder_init(shi->mode); + if (!shi->state) + goto out; + + ret = spx_ctl(shi->state, SPEEX_SET_ENH, &enh_enabled); + if (ret < 0) + goto out; + ret = spx_ctl(shi->state, SPEEX_GET_FRAME_SIZE, &shi->frame_size); + if (ret < 0) + goto out; + shi->sample_rate = h->rate; + ret = spx_ctl(shi->state, SPEEX_SET_SAMPLING_RATE, &shi->sample_rate); + if (ret < 0) + goto out; + shi->nframes = h->frames_per_packet; + shi->channels = h->nb_channels; + if (shi->channels != 1) { + shi->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT; + SpeexCallback callback = { + .callback_id = SPEEX_INBAND_STEREO, + .func = speex_std_stereo_request_handler, + .data = &shi->stereo, + }; + ret = spx_ctl(shi->state, SPEEX_SET_HANDLER, &callback); + if (ret < 0) + goto out; + shi->channels = 2; + } + ret = spx_ctl(shi->state, SPEEX_GET_BITRATE, &shi->bitrate); + if (ret < 0) + goto out; + PARA_NOTICE_LOG("%d Hz, %s, %s, %s, %d bits/s\n", + shi->sample_rate, shi->mode->modeName, + shi->channels == 1? "mono" : "stereo", + h->vbr? "vbr" : "cbr", + shi->bitrate + ); + shi->extra_headers = h->extra_headers; + ret = 1; +out: + free(h); + return ret; +}