mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 09:19:28 +00:00
Bug 422538. Import libfishsound
This commit is contained in:
parent
66e5749786
commit
c38cc109bc
22
modules/libfishsound/AUTHORS
Normal file
22
modules/libfishsound/AUTHORS
Normal file
@ -0,0 +1,22 @@
|
||||
Conrad Parker <conrad@metadecks.org>
|
||||
- Design, implementation.
|
||||
- Vorbis, Speex support
|
||||
|
||||
Tobias Gehrig
|
||||
- FLAC support
|
||||
|
||||
Silvia Pfeiffer <silvia@annodex.net>
|
||||
- MS Windows porting, general packaging.
|
||||
|
||||
Zentaro Kavanagh <ogg@illiminable.com>
|
||||
- Windows porting and packaging.
|
||||
|
||||
|
||||
based on code from:
|
||||
|
||||
libvorbis, by Monty <monty@xiph.org>, Xiph.org Foundation.
|
||||
|
||||
libspeex, by Jean-Marc Valin <jean-marc.valin@hermes.usherb.ca>,
|
||||
Xiph.Org Foundation
|
||||
|
||||
libFLAC, by Josh Coalson, Xiph.Org Foundation.
|
29
modules/libfishsound/COPYING
Normal file
29
modules/libfishsound/COPYING
Normal file
@ -0,0 +1,29 @@
|
||||
Copyright (C) 2003 CSIRO Australia
|
||||
|
||||
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 CSIRO 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 ORGANISATION 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.
|
||||
|
83
modules/libfishsound/ChangeLog
Normal file
83
modules/libfishsound/ChangeLog
Normal file
@ -0,0 +1,83 @@
|
||||
2007-01-12 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* Makefile.am:
|
||||
dist m4 macro
|
||||
* include/fishsound/Makefile.am:
|
||||
fix include directory when overriding includedir
|
||||
|
||||
2005-06-13 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* autogen.sh:
|
||||
* m4/as-ac-expand.m4:
|
||||
add m4 dir and use it
|
||||
add an expand macro
|
||||
* configure.ac:
|
||||
uniformize configure's output across the annodex stack
|
||||
|
||||
Thu Jan 13 17:58:45 EST 2005 Conrad Parker <conrad@metadecks.org>
|
||||
|
||||
* added liboil support from David Schleef <ds@schleef.org>
|
||||
|
||||
Thu Jun 24 18:48:46 EST 2004 Conrad Parker <conrad@metadecks.org>
|
||||
|
||||
* Version 0.6.3
|
||||
|
||||
Bug fixes:
|
||||
* non-interleaved Speex encoding re-written and tested
|
||||
* memory leak in comments API closed
|
||||
|
||||
Tests and examples:
|
||||
* new examples fishsound-encdec and fishsound-decenc to trial
|
||||
encode<->decode pipelines
|
||||
* improved testing of Speex non-interleaved encoding
|
||||
|
||||
Fri May 21 14:32:41 EST 2004 Conrad Parker <conrad@metadecks.org>
|
||||
|
||||
* Version 0.6.2
|
||||
|
||||
Improved handling of first and last blocks of data (bos and eos
|
||||
packets in Ogg):
|
||||
* new fish_sound_prepare_truncation() API call
|
||||
* improved encdec-audio test to keep track of frames in and out,
|
||||
and warn if unequal. (Currently not set to FAIL on this condition
|
||||
as it appears to be common for Speex)
|
||||
|
||||
Updates to Win32 nmake build files
|
||||
|
||||
Wed May 5 21:44:26 EST 2004 Conrad Parker <conrad@metadecks.org>
|
||||
|
||||
* Version 0.6.1
|
||||
|
||||
Added support for comment packets, tests, and various bugfixes.
|
||||
* Added fish_sound_comment_() API, <fishsound/comments.h>
|
||||
* Fixed segv bug in decoding stereo Speex to non-interleaved
|
||||
* Added test for encode/decode pipeline with a variety of
|
||||
combinations of format, interleave, samplerate, channels and
|
||||
buffer size.
|
||||
* Added tests for comments data structure and encode/decode pipeline
|
||||
|
||||
* Added fish_sound_{get,set}_frameno() API calls
|
||||
|
||||
Wed Mar 24 17:53:55 EST 2004 Conrad Parker <conrad@metadecks.org>
|
||||
|
||||
* Version 0.6.0
|
||||
* moved encode and decode to examples, added documentation for each
|
||||
* added fish_sound_{get,set}_interleave() api calls
|
||||
* various bugfixes from zen and silvia
|
||||
* updated win32 dev files from silvia
|
||||
|
||||
Sun Mar 07 17:30:00 EST 2004 Silvia Pfeiffer <Silvia.Pfeiffer@csiro.au>
|
||||
* Version 0.5.41
|
||||
* fixed up windows port and release preparation with
|
||||
REAME files etc.
|
||||
|
||||
|
||||
Some time in the year 2003...
|
||||
|
||||
* A new fish was born...
|
||||
|
||||
* ... by Conrad Parker <Conrad.Parker@csiro.au>
|
||||
|
||||
* ... and it had a long unlogged journey...
|
||||
|
||||
* before arriving at 0.5.40 . :)
|
51
modules/libfishsound/Makefile.in
Normal file
51
modules/libfishsound/Makefile.in
Normal file
@ -0,0 +1,51 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = fishsound
|
||||
|
||||
DIRS = \
|
||||
include \
|
||||
src \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
36
modules/libfishsound/README
Normal file
36
modules/libfishsound/README
Normal file
@ -0,0 +1,36 @@
|
||||
FishSound, the sound of fish!
|
||||
-----------------------------
|
||||
|
||||
Full documentation is available in doc/fishsound/html/index.html,
|
||||
or online at http://www.annodex.net/software/libfishsound/html/
|
||||
|
||||
Updates are available online at the FishSound homepage:
|
||||
http://www.annodex.net/software/libfishsound/
|
||||
|
||||
libfishsound provides a simple programming interface for decoding and
|
||||
encoding audio data using Xiph.Org codecs (FLAC, Speex and Vorbis).
|
||||
|
||||
libfishsound by itself is designed to handle raw codec streams from a
|
||||
lower level layer such as UDP datagrams. When these codecs are used in
|
||||
files, they are commonly encapsulated in Ogg to produce Ogg FLAC, Speex
|
||||
and Ogg Vorbis files.
|
||||
|
||||
This source tarball
|
||||
-------------------
|
||||
|
||||
FishSound has been developed and tested on GNU/Linux, Darwin/MacOSX
|
||||
and MS Windows. Installation uses the standard configure, make, make
|
||||
install sequence; Full details are in the file INSTALL. Read the file
|
||||
README.win32 for installing under MS Windows.
|
||||
|
||||
src/libfishsound/ the library source code.
|
||||
src/examples/ example tools for programming with libfishsound.
|
||||
|
||||
include/ the libfishound include files that will be installed
|
||||
into the system include directory.
|
||||
|
||||
doc/ documentation for libfishsound. The subdirectory
|
||||
doc/libfishsound is autocreated by doxygen from
|
||||
comments contained in <fishsound/fishsound.h>
|
||||
|
||||
win32/ files necessary to compile under MS Windows.
|
7
modules/libfishsound/README_MOZILLA
Normal file
7
modules/libfishsound/README_MOZILLA
Normal file
@ -0,0 +1,7 @@
|
||||
The source from this directory was copied from the libfishsound-0.9.1
|
||||
source distribution using the update.sh script. The only changes made
|
||||
were those applied by update.sh and the addition/upate of Makefile.in
|
||||
files for the Mozilla build system.
|
||||
|
||||
Some files are renamed during the copy to prevent clashes with object
|
||||
file names with other Mozilla libraries.
|
47
modules/libfishsound/include/Makefile.in
Normal file
47
modules/libfishsound/include/Makefile.in
Normal file
@ -0,0 +1,47 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = fishsound
|
||||
DIRS = fishsound
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
55
modules/libfishsound/include/fishsound/Makefile.in
Normal file
55
modules/libfishsound/include/fishsound/Makefile.in
Normal file
@ -0,0 +1,55 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = fishsound
|
||||
|
||||
EXPORTS = \
|
||||
comments.h \
|
||||
constants.h \
|
||||
decode.h \
|
||||
deprecated.h \
|
||||
encode.h \
|
||||
fishsound.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
211
modules/libfishsound/include/fishsound/comments.h
Normal file
211
modules/libfishsound/include/fishsound/comments.h
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_COMMENT_H__
|
||||
#define __FISH_SOUND_COMMENT_H__
|
||||
|
||||
/** \file
|
||||
* Encoding and decoding of comments.
|
||||
*
|
||||
* Vorbis and Speex bitstreams
|
||||
* use a comment format called "Vorbiscomment", defined
|
||||
* <a href="http://www.xiph.org/ogg/vorbis/doc/v-comment.html">here</a>.
|
||||
* Many standard comment names (such as TITLE, COPYRIGHT and GENRE) are
|
||||
* defined in that document.
|
||||
*
|
||||
* The following general features of Vorbiscomment are relevant to this API:
|
||||
* - Each stream has one comment packet, which occurs before any encoded
|
||||
* audio data in the stream.
|
||||
* - When encoding, FishSound will generate the comment block and pass it
|
||||
* to the encoded() callback in sequence, just like any other packet.
|
||||
* Hence, all comments must be set before any call to fish_sound_encode_*().
|
||||
* - When decoding, FishSound will decode the comment block before calling
|
||||
* the first decoded() callback. Hence, retrieving comment data is possible
|
||||
* from as soon as the decoded() callback is first called.
|
||||
*
|
||||
* Each comment block contains one Vendor string, which can be retrieved
|
||||
* with fish_sound_comment_get_vendor(). When encoding, this string is
|
||||
* effectively fixed by the codec libraries; it cannot be set by the
|
||||
* application.
|
||||
*
|
||||
* The rest of a comment block consists of \a name = \a value pairs, with
|
||||
* the following restrictions:
|
||||
* - Both the \a name and \a value must be non-empty
|
||||
* - The \a name is case-insensitive and must consist of ASCII within the
|
||||
* range 0x20 to 0x7D inclusive, 0x3D ('=') excluded.
|
||||
* - The \a name is not unique; multiple entries may exist with equivalent
|
||||
* \a name within a Vorbiscomment block.
|
||||
* - The \a value may be any UTF-8 string.
|
||||
*
|
||||
* \section comments_get Retrieving comments
|
||||
*
|
||||
* FishSound contains API methods to iterate through all comments associated
|
||||
* with a FishSound* handle (fish_sound_comment_first() and
|
||||
* fish_sound_comment_next(), and to iterate through comments matching a
|
||||
* particular name (fish_sound_comment_first_byname() and
|
||||
* fish_sound_comment_next_byname()). Given that multiple comments may exist
|
||||
* with the same \a name, you should not use
|
||||
* fish_sound_comment_first_byname() as a simple "get" function.
|
||||
*
|
||||
* \section comments_set Encoding comments
|
||||
*
|
||||
* For encoding, FishSound contains API methods for adding comments
|
||||
* (fish_sound_comment_add() and fish_sound_comment_add_byname()
|
||||
* and for removing comments
|
||||
* (fish_sound_comment_remove() and fish_sound_comment_remove_byname()).
|
||||
*/
|
||||
|
||||
#include <fishsound/fishsound.h>
|
||||
|
||||
/**
|
||||
* A comment.
|
||||
*/
|
||||
typedef struct {
|
||||
/** The name of the comment, eg. "AUTHOR" */
|
||||
char * name;
|
||||
|
||||
/** The value of the comment, as UTF-8 */
|
||||
char * value;
|
||||
} FishSoundComment;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Retrieve the vendor string.
|
||||
* \param fsound A FishSound* handle
|
||||
* \returns A read-only copy of the vendor string
|
||||
* \retval NULL No vendor string is associated with \a fsound,
|
||||
* or \a fsound is NULL.
|
||||
*/
|
||||
const char *
|
||||
fish_sound_comment_get_vendor (FishSound * fsound);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the first comment.
|
||||
* \param fsound A FishSound* handle
|
||||
* \returns A read-only copy of the first comment, or NULL if no comments
|
||||
* exist for this FishSound* object.
|
||||
*/
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_first (FishSound * fsound);
|
||||
|
||||
/**
|
||||
* Retrieve the next comment.
|
||||
* \param fsound A FishSound* handle
|
||||
* \param comment The previous comment.
|
||||
* \returns A read-only copy of the comment immediately following the given
|
||||
* comment.
|
||||
*/
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment);
|
||||
|
||||
/**
|
||||
* Retrieve the first comment with a given name.
|
||||
* \param fsound A FishSound* handle
|
||||
* \param name the name of the comment to retrieve.
|
||||
* \returns A read-only copy of the first comment matching the given \a name.
|
||||
* \retval NULL no match was found.
|
||||
* \note If \a name is NULL, the behaviour is the same as for
|
||||
* fish_sound_comment_first()
|
||||
*/
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_first_byname (FishSound * fsound, char * name);
|
||||
|
||||
/**
|
||||
* Retrieve the next comment following and with the same name as a given
|
||||
* comment.
|
||||
* \param fsound A FishSound* handle
|
||||
* \param comment A comment
|
||||
* \returns A read-only copy of the next comment with the same name as
|
||||
* \a comment.
|
||||
* \retval NULL no further comments with the same name exist for
|
||||
* this FishSound* object.
|
||||
*/
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_next_byname (FishSound * fsound,
|
||||
const FishSoundComment * comment);
|
||||
|
||||
/**
|
||||
* Add a comment
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
|
||||
* \param comment The comment to add
|
||||
* \retval 0 Success
|
||||
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
|
||||
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
|
||||
*/
|
||||
int
|
||||
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment);
|
||||
|
||||
/**
|
||||
* Add a comment by name and value.
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
|
||||
* \param name The name of the comment to add
|
||||
* \param value The contents of the comment to add
|
||||
* \retval 0 Success
|
||||
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
|
||||
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
|
||||
*/
|
||||
int
|
||||
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
|
||||
const char * value);
|
||||
|
||||
/**
|
||||
* Remove a comment
|
||||
* \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
|
||||
* \param comment The comment to remove.
|
||||
* \retval 1 Success: comment removed
|
||||
* \retval 0 No-op: comment not found, nothing to remove
|
||||
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
|
||||
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
|
||||
*/
|
||||
int
|
||||
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment);
|
||||
|
||||
/**
|
||||
* Remove all comments with a given name.
|
||||
* \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
|
||||
* \param name The name of the comments to remove
|
||||
* \retval ">= 0" The number of comments removed
|
||||
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
|
||||
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
|
||||
*/
|
||||
int
|
||||
fish_sound_comment_remove_byname (FishSound * fsound, char * name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FISH_SOUND_COMMENTS_H__ */
|
106
modules/libfishsound/include/fishsound/config.h
Normal file
106
modules/libfishsound/include/fishsound/config.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Do not build decoding support */
|
||||
#define FS_DECODE 1
|
||||
|
||||
/* Do not build encoding support */
|
||||
#define FS_ENCODE 0
|
||||
|
||||
/* Define to build experimental code */
|
||||
/* #undef FS_EXPERIMENTAL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have libFLAC */
|
||||
#define HAVE_FLAC 0
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define if have libsndfile */
|
||||
/* #undef HAVE_LIBSNDFILE1 */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define if have liboggz */
|
||||
/* #undef HAVE_OGGZ */
|
||||
|
||||
/* Define to 1 if you have libspeex */
|
||||
#define HAVE_SPEEX 0
|
||||
|
||||
/* Define to 1 if you have libspeex 1.1.x */
|
||||
/* #undef HAVE_SPEEX_1_1 */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have libvorbis */
|
||||
#define HAVE_VORBIS 1
|
||||
|
||||
/* Define to 1 if you have libvorbisenc */
|
||||
#define HAVE_VORBISENC 0
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libfishsound"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.9.1"
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
#undef FS_ENCODE
|
||||
#define FS_ENCODE 0
|
||||
#undef HAVE_FLAC
|
||||
#define HAVE_FLAC 0
|
||||
#undef HAVE_OGGZ
|
||||
#define HAVE_OGGZ 1
|
||||
#undef HAVE_SPEEX
|
||||
#define HAVE_SPEEX 0
|
||||
#undef HAVE_VORBIS
|
||||
#define HAVE_VORBIS 1
|
||||
#undef HAVE_VORBISENC
|
||||
#define HAVE_VORBISENC 0
|
||||
#undef DEBUG
|
119
modules/libfishsound/include/fishsound/constants.h
Normal file
119
modules/libfishsound/include/fishsound/constants.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_CONSTANTS_H__
|
||||
#define __FISH_SOUND_CONSTANTS_H__
|
||||
|
||||
/** \file
|
||||
* Constants used by libfishsound
|
||||
*/
|
||||
|
||||
/** Mode of operation (encode or decode) */
|
||||
typedef enum _FishSoundMode {
|
||||
/** Decode */
|
||||
FISH_SOUND_DECODE = 0x10,
|
||||
|
||||
/** Encode */
|
||||
FISH_SOUND_ENCODE = 0x20
|
||||
} FishSoundMode;
|
||||
|
||||
/** Identifiers for supported codecs */
|
||||
typedef enum _FishSoundCodecID {
|
||||
/** Unknown */
|
||||
FISH_SOUND_UNKNOWN = 0x00,
|
||||
|
||||
/** Vorbis */
|
||||
FISH_SOUND_VORBIS = 0x01,
|
||||
|
||||
/** Speex */
|
||||
FISH_SOUND_SPEEX = 0x02,
|
||||
|
||||
/** Flac */
|
||||
FISH_SOUND_FLAC = 0x03
|
||||
} FishSoundCodecID;
|
||||
|
||||
/** Decode callback return values */
|
||||
typedef enum _FishSoundStopCtl {
|
||||
/** Continue calling decode callbacks */
|
||||
FISH_SOUND_CONTINUE = 0,
|
||||
|
||||
/** Stop calling callbacks, but retain buffered data */
|
||||
FISH_SOUND_STOP_OK = 1,
|
||||
|
||||
/** Stop calling callbacks, and purge buffered data */
|
||||
FISH_SOUND_STOP_ERR = -1
|
||||
} FishSoundStopCtl;
|
||||
|
||||
/** Command codes */
|
||||
typedef enum _FishSoundCommand {
|
||||
/** No operation */
|
||||
FISH_SOUND_COMMAND_NOP = 0x0000,
|
||||
|
||||
/** Retrieve the FishSoundInfo */
|
||||
FISH_SOUND_GET_INFO = 0x1000,
|
||||
|
||||
/** Query if multichannel audio should be interpreted as interleaved */
|
||||
FISH_SOUND_GET_INTERLEAVE = 0x2000,
|
||||
|
||||
/** Set to 1 to interleave, 0 to non-interleave */
|
||||
FISH_SOUND_SET_INTERLEAVE = 0x2001,
|
||||
|
||||
FISH_SOUND_SET_ENCODE_VBR = 0x4000,
|
||||
|
||||
FISH_SOUND_COMMAND_MAX
|
||||
} FishSoundCommand;
|
||||
|
||||
/** Error values */
|
||||
typedef enum _FishSoundError {
|
||||
/** No error */
|
||||
FISH_SOUND_OK = 0,
|
||||
|
||||
/** generic error */
|
||||
FISH_SOUND_ERR_GENERIC = -1,
|
||||
|
||||
/** Not a valid FishSound* handle */
|
||||
FISH_SOUND_ERR_BAD = -2,
|
||||
|
||||
/** The requested operation is not suitable for this FishSound* handle */
|
||||
FISH_SOUND_ERR_INVALID = -3,
|
||||
|
||||
/** Functionality disabled at build time */
|
||||
FISH_SOUND_ERR_DISABLED = -10,
|
||||
|
||||
/** Too few bytes passed to fish_sound_identify() */
|
||||
FISH_SOUND_ERR_SHORT_IDENTIFY = -20,
|
||||
|
||||
/** Comment violates VorbisComment restrictions */
|
||||
FISH_SOUND_ERR_COMMENT_INVALID = -21
|
||||
} FishSoundError;
|
||||
|
||||
#endif /* __FISH_SOUND_CONSTANTS_H__ */
|
123
modules/libfishsound/include/fishsound/decode.h
Normal file
123
modules/libfishsound/include/fishsound/decode.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_DECODE_H__
|
||||
#define __FISH_SOUND_DECODE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file
|
||||
* Decode functions and callback prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Signature of a callback for libfishsound to call when it has decoded
|
||||
* PCM audio data, and you want this provided as non-interleaved floats.
|
||||
* \param fsound The FishSound* handle
|
||||
* \param pcm The decoded audio
|
||||
* \param frames The count of frames decoded
|
||||
* \param user_data Arbitrary user data
|
||||
* \retval FISH_SOUND_CONTINUE Continue decoding
|
||||
* \retval FISH_SOUND_STOP_OK Stop decoding immediately and
|
||||
* return control to the fish_sound_decode() caller
|
||||
* \retval FISH_SOUND_STOP_ERR Stop decoding immediately, purge buffered
|
||||
* data, and return control to the fish_sound_decode() caller
|
||||
*/
|
||||
typedef int (*FishSoundDecoded_Float) (FishSound * fsound, float * pcm[],
|
||||
long frames, void * user_data);
|
||||
|
||||
/**
|
||||
* Signature of a callback for libfishsound to call when it has decoded
|
||||
* PCM audio data, and you want this provided as interleaved floats.
|
||||
* \param fsound The FishSound* handle
|
||||
* \param pcm The decoded audio
|
||||
* \param frames The count of frames decoded
|
||||
* \param user_data Arbitrary user data
|
||||
* \retval FISH_SOUND_CONTINUE Continue decoding
|
||||
* \retval FISH_SOUND_STOP_OK Stop decoding immediately and
|
||||
* return control to the fish_sound_decode() caller
|
||||
* \retval FISH_SOUND_STOP_ERR Stop decoding immediately, purge buffered
|
||||
* data, and return control to the fish_sound_decode() caller
|
||||
*/
|
||||
typedef int (*FishSoundDecoded_FloatIlv) (FishSound * fsound, float ** pcm,
|
||||
long frames, void * user_data);
|
||||
|
||||
/**
|
||||
* Set the callback for libfishsound to call when it has a block of decoded
|
||||
* PCM audio ready, and you want this provided as non-interleaved floats.
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
|
||||
* \param decoded The callback to call
|
||||
* \param user_data Arbitrary user data to pass to the callback
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_set_decoded_float (FishSound * fsound,
|
||||
FishSoundDecoded_Float decoded,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Set the callback for libfishsound to call when it has a block of decoded
|
||||
* PCM audio ready, and you want this provided as interleaved floats.
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
|
||||
* \param decoded The callback to call
|
||||
* \param user_data Arbitrary user data to pass to the callback
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_set_decoded_float_ilv (FishSound * fsound,
|
||||
FishSoundDecoded_FloatIlv decoded,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Decode a block of compressed data.
|
||||
* No internal buffering is done, so a complete compressed audio packet
|
||||
* must be passed each time.
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
|
||||
* \param buf A buffer containing a compressed audio packet
|
||||
* \param bytes A count of bytes to decode (i.e. the length of buf)
|
||||
* \returns The number of bytes consumed
|
||||
* \retval FISH_SOUND_ERR_STOP_OK Decoding was stopped by a FishSoundDecode*
|
||||
* callback returning FISH_SOUND_STOP_OK before any input bytes were consumed.
|
||||
* This will occur when PCM is decoded from previously buffered input, and
|
||||
* stopping is immediately requested.
|
||||
* \retval FISH_SOUND_ERR_STOP_ERR Decoding was stopped by a FishSoundDecode*
|
||||
* callback returning FISH_SOUND_STOP_ERR before any input bytes were consumed.
|
||||
* This will occur when PCM is decoded from previously buffered input, and
|
||||
* stopping is immediately requested.
|
||||
*/
|
||||
long fish_sound_decode (FishSound * fsound, unsigned char * buf, long bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FISH_SOUND_DECODE_H__ */
|
128
modules/libfishsound/include/fishsound/deprecated.h
Normal file
128
modules/libfishsound/include/fishsound/deprecated.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_DEPRECATED_H__
|
||||
#define __FISH_SOUND_DEPRECATED_H__
|
||||
|
||||
/** \file
|
||||
* Deprecated interfaces
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DEPRECATED FUNCTION.
|
||||
* Set the PCM format used by a FishSound object. The default value is
|
||||
* non-interleaved.
|
||||
* Prior to libfishsound 0.7.0, you would (optionally) specify whether you
|
||||
* wanted to receive interleaved or per-channel PCM data using
|
||||
* fish_sound_set_interleave(), the default being per-channel
|
||||
* (non-interleaved) PCM.
|
||||
* Whether or not your decoded callback expects interleaved or
|
||||
* non-interleaved data is now implied by the particular
|
||||
* fish_sound_set_decoded_TYPE() method you use to set it, such as
|
||||
* fish_sound_set_decoded_float() or fish_sound_set_decode_float_ilv().
|
||||
*
|
||||
* \param fsound A FishSound* handle
|
||||
* \param interleave Whether to use interleaved PCM or not. Valid values are
|
||||
* 0 for non-interleaved, and 1 for interleaved.
|
||||
* \retval 0 Success
|
||||
* \retval -1 Invalid \a fsound
|
||||
*/
|
||||
int fish_sound_set_interleave (FishSound * fsound, int interleave);
|
||||
|
||||
/**
|
||||
* DEPRECATED TYPE.
|
||||
* Signature of a callback for libfishsound to call when it has decoded
|
||||
* PCM audio data, and you want this provided as floats using the current
|
||||
* interleave method as set by fish_sound_set_interleave().
|
||||
*/
|
||||
typedef FishSoundDecoded_Float FishSoundDecoded;
|
||||
|
||||
/**
|
||||
* DEPRECATED FUNCTION.
|
||||
* Set the callback for libfishsound to call when it has a block of decoded
|
||||
* PCM audio ready, and you want this provided as floats using the current
|
||||
* interleave method as set by fish_sound_set_interleave().
|
||||
* This function, and fish_sound_set_interleave(), have been superceded by
|
||||
* the typesafe fish_sound_set_decoded_TYPE() callbacks, such as
|
||||
* fish_sound_set_decoded_float() or fish_sound_set_decoded_float_ilv().
|
||||
*
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
|
||||
* \param decoded The callback to call
|
||||
* \param user_data Arbitrary user data to pass to the callback
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_set_decoded_callback (FishSound * fsound,
|
||||
FishSoundDecoded decoded,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* DEPRECATED FUNCTION.
|
||||
* Set the PCM format used by a FishSound object. The default value is
|
||||
* non-interleaved.
|
||||
* Prior to libfishsound 0.7.0, you would (optionally) specify whether you
|
||||
* wanted to receive interleaved or per-channel PCM data using
|
||||
* fish_sound_set_interleave(), the default being per-channel
|
||||
* (non-interleaved) PCM.
|
||||
* Whether or not your decoded callback expects interleaved or
|
||||
* non-interleaved data is now implied by the particular
|
||||
* fish_sound_set_decoded_TYPE() method you use to set it, such as
|
||||
* fish_sound_set_decoded_float() or fish_sound_set_decode_float_ilv().
|
||||
*
|
||||
* \param fsound A FishSound* handle
|
||||
* \param interleave Whether to use interleaved PCM or not. Valid values are
|
||||
* 0 for non-interleaved, and 1 for interleaved.
|
||||
* \retval 0 Success
|
||||
* \retval -1 Invalid \a fsound
|
||||
*/
|
||||
int fish_sound_set_interleave (FishSound * fsound, int interleave);
|
||||
|
||||
/**
|
||||
* DEPRECATED FUNCTION.
|
||||
* Encode a block of audio
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
|
||||
* \param pcm The audio data to encode
|
||||
* \param frames A count of frames to encode
|
||||
* \returns The number of frames encoded
|
||||
* \note For multichannel audio, the audio data is interpreted according
|
||||
* to the current PCM style
|
||||
*/
|
||||
long fish_sound_encode (FishSound * fsound, float ** pcm, long frames);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FISH_SOUND_DEPRECATED_H__ */
|
97
modules/libfishsound/include/fishsound/encode.h
Normal file
97
modules/libfishsound/include/fishsound/encode.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_ENCODE_H__
|
||||
#define __FISH_SOUND_ENCODE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file
|
||||
* Encode functions and callback prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Signature of a callback for libfishsound to call when it has encoded
|
||||
* data.
|
||||
* \param fsound The FishSound* handle
|
||||
* \param buf The encoded data
|
||||
* \param bytes The count of bytes encoded
|
||||
* \param user_data Arbitrary user data
|
||||
* \retval 0 to continue
|
||||
* \retval non-zero to stop encoding immediately and
|
||||
* return control to the fish_sound_encode() caller
|
||||
*/
|
||||
typedef int (*FishSoundEncoded) (FishSound * fsound, unsigned char * buf,
|
||||
long bytes, void * user_data);
|
||||
|
||||
/**
|
||||
* Set the callback for libfishsound to call when it has a block of
|
||||
* encoded data ready
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
|
||||
* \param encoded The callback to call
|
||||
* \param user_data Arbitrary user data to pass to the callback
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_set_encoded_callback (FishSound * fsound,
|
||||
FishSoundEncoded encoded,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Encode a block of PCM audio given as non-interleaved floats.
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
|
||||
* \param pcm The audio data to encode
|
||||
* \param frames A count of frames to encode
|
||||
* \returns The number of frames encoded
|
||||
* \note For multichannel audio, the audio data is interpreted according
|
||||
* to the current PCM style
|
||||
*/
|
||||
long fish_sound_encode_float (FishSound * fsound, float * pcm[], long frames);
|
||||
|
||||
/**
|
||||
* Encode a block of audio given as interleaved floats.
|
||||
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
|
||||
* \param pcm The audio data to encode
|
||||
* \param frames A count of frames to encode
|
||||
* \returns The number of frames encoded
|
||||
* \note For multichannel audio, the audio data is interpreted according
|
||||
* to the current PCM style
|
||||
*/
|
||||
long fish_sound_encode_float_ilv (FishSound * fsound, float ** pcm,
|
||||
long frames);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FISH_SOUND_ENCODE_H__ */
|
589
modules/libfishsound/include/fishsound/fishsound.h
Normal file
589
modules/libfishsound/include/fishsound/fishsound.h
Normal file
@ -0,0 +1,589 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_H__
|
||||
#define __FISH_SOUND_H__
|
||||
|
||||
#include <fishsound/constants.h>
|
||||
|
||||
/** \mainpage
|
||||
*
|
||||
* \section intro FishSound, the sound of fish!
|
||||
*
|
||||
* This is the documentation for the FishSound C API. FishSound provides
|
||||
* a simple programming interface for decoding and encoding audio data
|
||||
* using Xiph.Org codecs (FLAC, Speex and Vorbis).
|
||||
*
|
||||
* libfishsound by itself is designed to handle raw codec streams from
|
||||
* a lower level layer such as UDP datagrams.
|
||||
* When these codecs are used in files, they are commonly encapsulated in
|
||||
* <a href="http://www.xiph.org/ogg/">Ogg</a> to produce
|
||||
* <em>Ogg FLAC</em>, <em>Speex</em> and <em>Ogg Vorbis</em> files.
|
||||
* Example C programs using
|
||||
* <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
|
||||
* read and write these files are provided in the libfishsound sources.
|
||||
*
|
||||
* For more information on the design and history of libfishsound, see the
|
||||
* \link about About \endlink section of this documentation, and the
|
||||
* <a href="http://www.annodex.net/software/libfishsound/">libfishsound</a>
|
||||
* homepage.
|
||||
*
|
||||
* \subsection contents Contents
|
||||
*
|
||||
* - \link fishsound.h fishsound.h \endlink:
|
||||
* Documentation of the FishSound API.
|
||||
*
|
||||
* - \link comments.h Handling comments \endlink:
|
||||
* How to add and retrieve \a name = \a value metadata in Vorbis and Speex
|
||||
* streams.
|
||||
*
|
||||
* - \link decode Decoding audio data \endlink:
|
||||
* How to decode audio data with FishSound, including source for a fully
|
||||
* working Ogg FLAC, Speex and Ogg Vorbis decoder.
|
||||
*
|
||||
* - \link encode Encoding audio data \endlink:
|
||||
* How to encode audio data with FishSound, including source for a fully
|
||||
* working Ogg FLAC, Speex and Ogg Vorbis encoder.
|
||||
*
|
||||
* - \link configuration Configuration \endlink:
|
||||
* Customizing libfishsound to only decode or encode,
|
||||
* or to disable support for a particular codec.
|
||||
*
|
||||
* - \link building Building \endlink:
|
||||
* Information related to building software that uses libfishsound.
|
||||
*
|
||||
* - \link about About \endlink:
|
||||
* Design, motivation, history and acknowledgements.
|
||||
*
|
||||
* \section Licensing
|
||||
*
|
||||
* libfishsound is provided under the following BSD-style open source license:
|
||||
*
|
||||
* \include COPYING
|
||||
*
|
||||
*/
|
||||
|
||||
/** \defgroup about About
|
||||
*
|
||||
* \section design Design
|
||||
* libfishsound provides a simple programming interface for decoding and
|
||||
* encoding audio data using codecs from
|
||||
* <a href="http://www.xiph.org/">Xiph.Org</a>.
|
||||
*
|
||||
* libfishsound by itself is designed to handle raw codec streams from
|
||||
* a lower level layer such as UDP datagrams.
|
||||
* When these codecs are used in files, they are commonly encapsulated in
|
||||
* <a href="http://www.xiph.org/ogg/">Ogg</a> to produce
|
||||
* <em>Ogg FLAC</em>, <em>Speex</em> and <em>Ogg Vorbis</em> files.
|
||||
* Example C programs using
|
||||
* <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
|
||||
* read and write these files are provided in the libfishsound sources.
|
||||
*
|
||||
* libfishsound is implemented as a wrapper around the existing codec
|
||||
* libraries and provides a consistent, higher-level programming
|
||||
* interface. The motivation for this is twofold: to simplify the task
|
||||
* of developing application software that supports these codecs,
|
||||
* and to ensure that valid codec streams are generated.
|
||||
*
|
||||
* \section history History
|
||||
* libfishsound was designed and developed by Conrad Parker on the
|
||||
* weekend of October 18-19 2003. Previously the author had implemented
|
||||
* Vorbis and Speex support in the following software:
|
||||
* - <a href="http://www.metadecks.org/software/sweep/">Sweep</a>, a
|
||||
* digital audio editor with decoding and GUI control of all encoding
|
||||
* options of Vorbis and Speex
|
||||
* - Speex support in the <a href="http://www.xinehq.org/">xine</a>
|
||||
* multimedia player
|
||||
* - Vorbis and Speex importers for
|
||||
* <a href="http://www.annodex.net/software/libannodex/">libannodex</a>,
|
||||
the basic library for reading and writing
|
||||
* <a href="http://www.annodex.net/">Annodex.net</a> media files.
|
||||
*
|
||||
* The implementation of libfishsound draws heavily on these sources, and
|
||||
* in turn the original example sources of libvorbis and libvorbisenc by
|
||||
* Monty, and libspeex by Jean-Marc Valin.
|
||||
*
|
||||
* The naming of libfishsound reflects both the Xiph.Org logo and
|
||||
* the author's reputation as a dirty, smelly old fish.
|
||||
*
|
||||
* \section limitations Limitations
|
||||
*
|
||||
* libfishsound has been designed to accomodate the various decoding and
|
||||
* encoding styles required by a wide variety of software. However, as it
|
||||
* is an abstraction of the underlying libvorbis, libvorbisenc and libspeex
|
||||
* libraries, it may not be possible to implement some low-level techniques
|
||||
* that these libraries enable, such as parallelization of Vorbis sub-block
|
||||
* decoding. Nevertheless it is expected that libfishsound is a useful
|
||||
* API for most software requiring Vorbis or Speex support, including most
|
||||
* applications the author has encountered.
|
||||
*
|
||||
* \section acknowledgements Acknowledgements
|
||||
* Much of the API design follows the style of
|
||||
* <a href="http://www.zip.com.au/~erikd/libsndfile/">libsndfile</a>.
|
||||
* The author would like to thank Erik de Castro Lopo for feedback on the
|
||||
* design of libfishsound.
|
||||
*/
|
||||
|
||||
/** \defgroup configuration Configuration
|
||||
*
|
||||
* \section platforms Platform-specific configuration
|
||||
*
|
||||
* FishSound can be configured on most platforms using the GNU autoconf
|
||||
* ./configure system described below.
|
||||
*
|
||||
* For Win32, see the \link win32 README.win32 \endlink section. You will
|
||||
* need to edit <tt>win32/config.h</tt> by hand to achieve the customizations
|
||||
* described below.
|
||||
*
|
||||
* \section ./configure ./configure
|
||||
*
|
||||
* It is possible to customize the functionality of libfishsound
|
||||
* by using various ./configure flags when
|
||||
* building it from source; for example you can build a smaller
|
||||
* version of libfishsound to only decode or encode, or and you can
|
||||
* choose to disable support for a particular codec.
|
||||
* By default, both decoding and encoding support is built for all
|
||||
* codecs found on the system.
|
||||
*
|
||||
* For general information about using ./configure, see the file
|
||||
* \link install INSTALL \endlink
|
||||
*
|
||||
* \subsection no_encode Removing encoding support
|
||||
*
|
||||
* Configuring with \a --disable-encode will remove all support for encoding:
|
||||
* - All internal encoding related functions will not be built
|
||||
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
|
||||
* will fail, returning NULL
|
||||
* - Any attempt to call fish_sound_encode_*() will return
|
||||
* FISH_SOUND_ERR_DISABLED
|
||||
* - The resulting library will not be linked against libvorbisenc
|
||||
*
|
||||
* \subsection no_decode Removing decoding support
|
||||
*
|
||||
* Configuring with \a --disable-decode will remove all support for decoding:
|
||||
* - All internal decoding related functions will not be built
|
||||
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_DECODE
|
||||
* will fail, returning NULL
|
||||
* - Any attempt to call fish_sound_decode() will return
|
||||
* FISH_SOUND_ERR_DISABLED
|
||||
*
|
||||
* \subsection no_flac Removing FLAC support
|
||||
*
|
||||
* Configuring with \a --disable-flac will remove all support for FLAC:
|
||||
* - All internal FLAC related functions will not be built
|
||||
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
|
||||
* and \a fsinfo->format == FISH_SOUND_FLAC will fail, returning NULL
|
||||
* - The resulting library will not be linked against libFLAC
|
||||
*
|
||||
* \subsection no_speex Removing Speex support
|
||||
*
|
||||
* Configuring with \a --disable-speex will remove all support for Speex:
|
||||
* - All internal Speex related functions will not be built
|
||||
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
|
||||
* and \a fsinfo->format == FISH_SOUND_SPEEX will fail, returning NULL
|
||||
* - The resulting library will not be linked against libspeex
|
||||
*
|
||||
* \subsection no_vorbis Removing Vorbis support
|
||||
*
|
||||
* Configuring with \a --disable-vorbis will remove all support for Vorbis:
|
||||
* - All internal Vorbis related functions will not be built
|
||||
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
|
||||
* and \a fsinfo->format == FISH_SOUND_VORBIS will fail, returning NULL
|
||||
* - The resulting library will not be linked against libvorbis or libvorbisenc
|
||||
*
|
||||
* \subsection summary Configuration summary
|
||||
*
|
||||
* Upon successful configuration, you should see something like this:
|
||||
<pre>
|
||||
------------------------------------------------------------------------
|
||||
libfishsound 0.9.0: Automatic configuration OK.
|
||||
|
||||
General configuration:
|
||||
|
||||
Experimental code: ........... no
|
||||
Decoding support: ............ yes
|
||||
Encoding support: ............ yes
|
||||
|
||||
Library configuration (./src/libfishsound):
|
||||
|
||||
FLAC support: ................ yes
|
||||
Speex support: ............... yes (1.1.x)
|
||||
Vorbis support: .............. yes
|
||||
|
||||
Example programs (./src/examples):
|
||||
|
||||
fishsound-identify fishsound-decode fishsound-encode
|
||||
|
||||
Installation paths:
|
||||
|
||||
libfishsound: ................ /usr/local/lib
|
||||
C header files: .............. /usr/local/include/fishsound
|
||||
Documentation: ............... /usr/local/share/doc/libfishsound
|
||||
|
||||
Building:
|
||||
|
||||
Type 'make' to compile libfishsound.
|
||||
|
||||
Type 'make install' to install libfishsound.
|
||||
|
||||
Type 'make check' to run test suite (Valgrind testing not enabled)
|
||||
|
||||
Example programs will be built but not installed.
|
||||
------------------------------------------------------------------------
|
||||
</pre>
|
||||
*/
|
||||
|
||||
/** \defgroup install Installation
|
||||
* \section install INSTALL
|
||||
*
|
||||
* \include INSTALL
|
||||
*/
|
||||
|
||||
/** \defgroup win32 Building on Win32
|
||||
* \section win32 README.Win32
|
||||
*
|
||||
* \include README.win32
|
||||
*/
|
||||
|
||||
/** \defgroup building Building against libfishsound
|
||||
*
|
||||
*
|
||||
* \section autoconf Using GNU autoconf
|
||||
*
|
||||
* If you are using GNU autoconf, you do not need to call pkg-config
|
||||
* directly. Use the following macro to determine if libfishsound is
|
||||
* available:
|
||||
*
|
||||
<pre>
|
||||
PKG_CHECK_MODULES(FISHSOUND, fishsound >= 0.6.0,
|
||||
HAVE_FISHSOUND="yes", HAVE_FISHSOUND="no")
|
||||
if test "x$HAVE_FISHSOUND" = "xyes" ; then
|
||||
AC_SUBST(FISHSOUND_CFLAGS)
|
||||
AC_SUBST(FISHSOUND_LIBS)
|
||||
fi
|
||||
</pre>
|
||||
* (Note that if your application requires FLAC support, you should check
|
||||
* for a version of fishsound >= 0.9.0).
|
||||
*
|
||||
* If libfishsound is found, HAVE_FISHSOUND will be set to "yes", and
|
||||
* the autoconf variables FISHSOUND_CFLAGS and FISHSOUND_LIBS will
|
||||
* be set appropriately.
|
||||
*
|
||||
* \section pkg-config Determining compiler options with pkg-config
|
||||
*
|
||||
* If you are not using GNU autoconf in your project, you can use the
|
||||
* pkg-config tool directly to determine the correct compiler options.
|
||||
*
|
||||
<pre>
|
||||
FISHSOUND_CFLAGS=`pkg-config --cflags fishsound`
|
||||
|
||||
FISHSOUND_LIBS=`pkg-config --libs fishsound`
|
||||
</pre>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* The libfishsound C API.
|
||||
*
|
||||
* \section general General usage
|
||||
*
|
||||
* All access is managed via a FishSound* handle. This is instantiated
|
||||
* using fish_sound_new() and should be deleted with fish_sound_delete()
|
||||
* when no longer required. If there is a discontinuity in the input
|
||||
* data (eg. after seeking in an input file), call fish_sound_reset() to
|
||||
* reset the internal codec state.
|
||||
*
|
||||
* \section decoding Decoding
|
||||
*
|
||||
* libfishsound provides callback based decoding: you feed it encoded audio
|
||||
* data, and it will call your callback with decoded PCM. A more detailed
|
||||
* explanation and a full example of decoding Ogg FLAC, Speex and Ogg Vorbis
|
||||
* files is provided in the \link decode Decoding audio data \endlink section.
|
||||
*
|
||||
* \section encoding Encoding
|
||||
*
|
||||
* libfishsound provides callback based encoding: you feed it PCM audio,
|
||||
* and it will call your callback with encoded audio data. A more detailed
|
||||
* explanation and a full example of encoding Ogg FLAC, Speex and Ogg Vorbis
|
||||
* files is provided in the \link encode Encoding audio data \endlink section.
|
||||
*/
|
||||
|
||||
/** \defgroup decode Decoding audio data
|
||||
*
|
||||
* To decode audio data using libfishsound:
|
||||
*
|
||||
* - create a FishSound* object with mode FISH_SOUND_DECODE. fish_sound_new()
|
||||
* will return a new FishSound* object, initialised for decoding, and the
|
||||
* FishSoundInfo structure will be cleared.
|
||||
* - provide a FishSoundDecoded_* callback for libfishsound to call when it has
|
||||
* decoded audio.
|
||||
* - (optionally) specify whether you want to receive interleaved or
|
||||
* per-channel PCM data, using a fish_sound_set_interleave().
|
||||
* The default is for per-channel (non-interleaved) PCM.
|
||||
* - feed encoded audio data to libfishsound via fish_sound_decode().
|
||||
* libfishsound will decode the audio for you, calling the FishSoundDecoded_*
|
||||
* callback you provided earlier each time it has a block of audio ready.
|
||||
* - when finished, call fish_sound_delete().
|
||||
*
|
||||
* This procedure is illustrated in src/examples/fishsound-decode.c.
|
||||
* Note that this example additionally:
|
||||
* - uses <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
|
||||
* demultiplex audio data from an Ogg encapsulated FLAC, Speex or Vorbis
|
||||
* stream. The step of feeding encoded data to libfishsound is done within
|
||||
* the OggzReadPacket callback.
|
||||
* - uses <a href="http://www.mega-nerd.com/libsndfile/">libsndfile</a> to
|
||||
* write the decoded audio to a WAV file.
|
||||
*
|
||||
* Hence this example code demonstrates all that is needed to decode
|
||||
* Ogg FLAC, Speex or Ogg Vorbis files:
|
||||
*
|
||||
* \include fishsound-decode.c
|
||||
*/
|
||||
|
||||
/** \defgroup encode Encoding audio data
|
||||
*
|
||||
* To encode audio data using libfishsound:
|
||||
*
|
||||
* - create a FishSound* object with mode FISH_SOUND_ENCODE, and with a
|
||||
* FishSoundInfo structure filled in with the required encoding parameters.
|
||||
* fish_sound_new() will return a new FishSound* object initialised for
|
||||
* encoding.
|
||||
* - provide a FishSoundEncoded callback for libfishsound to call when it
|
||||
* has a block of encoded audio
|
||||
* - feed raw PCM audio data to libfishsound via fish_sound_encode_*().
|
||||
* libfishsound will encode the audio for you, calling the FishSoundEncoded
|
||||
* callback you provided earlier each time it has a block of encoded audio
|
||||
* ready.
|
||||
* - when finished, call fish_sound_delete().
|
||||
*
|
||||
* This procedure is illustrated in src/examples/fishsound-encode.c.
|
||||
* Note that this example additionally:
|
||||
* - uses <a href="http://www.mega-nerd.com/libsndfile/">libsndfile</a> to
|
||||
* read input from a PCM audio file (WAV, AIFF, etc.)
|
||||
* - uses <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
|
||||
* encapsulate the encoded FLAC, Speex or Vorbis data in an Ogg stream.
|
||||
*
|
||||
* Hence this example code demonstrates all that is needed to encode
|
||||
* Ogg FLAC, Speex and Ogg Vorbis files:
|
||||
*
|
||||
* \include fishsound-encode.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* Info about a particular encoder/decoder instance
|
||||
*/
|
||||
typedef struct {
|
||||
/** Sample rate of audio data in Hz */
|
||||
int samplerate;
|
||||
|
||||
/** Count of channels */
|
||||
int channels;
|
||||
|
||||
/** FISH_SOUND_VORBIS, FISH_SOUND_SPEEX, FISH_SOUND_FLAC etc. */
|
||||
int format;
|
||||
} FishSoundInfo;
|
||||
|
||||
/**
|
||||
* Info about a particular sound format
|
||||
*/
|
||||
typedef struct {
|
||||
/** FISH_SOUND_VORBIS, FISH_SOUND_SPEEX, FISH_SOUND_FLAC etc. */
|
||||
int format;
|
||||
|
||||
/** Printable name */
|
||||
const char * name;
|
||||
|
||||
/** Commonly used file extension */
|
||||
const char * extension;
|
||||
} FishSoundFormat;
|
||||
|
||||
/**
|
||||
* An opaque handle to a FishSound. This is returned by fishsound_new()
|
||||
* and is passed to all other fish_sound_*() functions.
|
||||
*/
|
||||
typedef void * FishSound;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Identify a codec based on the first few bytes of data.
|
||||
* \param buf A pointer to the first few bytes of the data
|
||||
* \param bytes The count of bytes available at buf
|
||||
* \retval FISH_SOUND_xxxxxx FISH_SOUND_VORBIS, FISH_SOUND_SPEEX or
|
||||
* FISH_SOUND_FLAC if \a buf was identified as the initial bytes of a
|
||||
* supported codec
|
||||
* \retval FISH_SOUND_UNKNOWN if the codec could not be identified
|
||||
* \retval FISH_SOUND_ERR_SHORT_IDENTIFY if \a bytes is less than 8
|
||||
* \note If \a bytes is exactly 8, then only a weak check is performed,
|
||||
* which is fast but may return a false positive.
|
||||
* \note If \a bytes is greater than 8, then a stronger check is performed
|
||||
* in which an attempt is made to decode \a buf as the initial header of
|
||||
* each supported codec. This is unlikely to return a false positive but
|
||||
* is only useful if \a buf is the entire payload of a packet derived from
|
||||
* a lower layer such as Ogg framing or UDP datagrams.
|
||||
*/
|
||||
int
|
||||
fish_sound_identify (unsigned char * buf, long bytes);
|
||||
|
||||
/**
|
||||
* Instantiate a new FishSound* handle
|
||||
* \param mode FISH_SOUND_DECODE or FISH_SOUND_ENCODE
|
||||
* \param fsinfo Encoder configuration, may be NULL for FISH_SOUND_DECODE
|
||||
* \returns A new FishSound* handle, or NULL on error
|
||||
*/
|
||||
FishSound * fish_sound_new (int mode, FishSoundInfo * fsinfo);
|
||||
|
||||
/**
|
||||
* Flush any internally buffered data, forcing encode
|
||||
* \param fsound A FishSound* handle
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
long fish_sound_flush (FishSound * fsound);
|
||||
|
||||
/**
|
||||
* Reset the codec state of a FishSound object.
|
||||
*
|
||||
* When decoding from a seekable file, fish_sound_reset() should be called
|
||||
* after any seek operations. See also fish_sound_set_frameno().
|
||||
*
|
||||
* \param fsound A FishSound* handle
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_reset (FishSound * fsound);
|
||||
|
||||
/**
|
||||
* Delete a FishSound object
|
||||
* \param fsound A FishSound* handle
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_delete (FishSound * fsound);
|
||||
|
||||
/**
|
||||
* Command interface
|
||||
* \param fsound A FishSound* handle
|
||||
* \param command The command action
|
||||
* \param data Command data
|
||||
* \param datasize Size of the data in bytes
|
||||
* \returns 0 on success, -1 on failure
|
||||
*/
|
||||
int fish_sound_command (FishSound * fsound, int command, void * data,
|
||||
int datasize);
|
||||
|
||||
/**
|
||||
* Query whether a FishSound object is using interleaved PCM
|
||||
* \param fsound A FishSound* handle
|
||||
* \retval 0 \a fsound uses non-interleaved PCM
|
||||
* \retval 1 \a fsound uses interleaved PCM
|
||||
* \retval -1 Invalid \a fsound
|
||||
*/
|
||||
int fish_sound_get_interleave (FishSound * fsound);
|
||||
|
||||
/**
|
||||
* Query the current frame number of a FishSound object.
|
||||
*
|
||||
* For decoding, this is the greatest frame index that has been decoded and
|
||||
* made available to a FishSoundDecoded callback. This function is safe to
|
||||
* call from within a FishSoundDecoded callback, and corresponds to the frame
|
||||
* number of the last frame in the current decoded block.
|
||||
*
|
||||
* For encoding, this is the greatest frame index that has been encoded. This
|
||||
* function is safe to call from within a FishSoundEncoded callback, and
|
||||
* corresponds to the frame number of the last frame encoded in the current
|
||||
* block.
|
||||
*
|
||||
* \param fsound A FishSound* handle
|
||||
* \returns The current frame number
|
||||
* \retval -1 Invalid \a fsound
|
||||
*/
|
||||
long fish_sound_get_frameno (FishSound * fsound);
|
||||
|
||||
/**
|
||||
* Set the current frame number of a FishSound object.
|
||||
*
|
||||
* When decoding from a seekable file, fish_sound_set_frameno() should be
|
||||
* called after any seek operations, otherwise the value returned by
|
||||
* fish_sound_get_frameno() will simply continue to increment. See also
|
||||
* fish_sound_reset().
|
||||
*
|
||||
* \param fsound A FishSound* handle
|
||||
* \param frameno The current frame number.
|
||||
* \retval 0 Success
|
||||
* \retval -1 Invalid \a fsound
|
||||
*/
|
||||
int fish_sound_set_frameno (FishSound * fsound, long frameno);
|
||||
|
||||
/**
|
||||
* Prepare truncation details for the next block of data.
|
||||
* The semantics of these parameters derives directly from Ogg encapsulation
|
||||
* of Vorbis, described
|
||||
* <a href="http://www.xiph.org/ogg/vorbis/doc/Vorbis_I_spec.html#vorbis-over-ogg">here</a>.
|
||||
*
|
||||
* When decoding from Ogg, you should call this function with the \a granulepos
|
||||
* and \a eos of the \a ogg_packet structure. This call should be made before
|
||||
* passing the packet's data to fish_sound_decode(). Failure to do so may
|
||||
* result in minor decode errors on the first and/or last packet of the stream.
|
||||
*
|
||||
* When encoding into Ogg, you should call this function with the \a granulepos
|
||||
* and \a eos that will be used for the \a ogg_packet structure. This call
|
||||
* should be made before passing the block of audio data to
|
||||
* fish_sound_encode_*(). Failure to do so may result in minor encoding errors
|
||||
* on the first and/or last packet of the stream.
|
||||
*
|
||||
* \param fsound A FishSound* handle
|
||||
* \param next_granulepos The "granulepos" for the next block to decode.
|
||||
* If unknown, set \a next_granulepos to -1. Otherwise,
|
||||
* \a next_granulepos specifies the frameno of the final frame in the
|
||||
* block. This is authoritative, hence can be used to indicate
|
||||
* various forms of truncation at the beginning or end of a stream.
|
||||
* Mid-stream, a later-than-expected "granulepos" indicates that some
|
||||
* data was missing.
|
||||
* \param next_eos A boolean indicating whether the next data block will be
|
||||
* the last in the stream.
|
||||
* \retval 0 Success
|
||||
* \retval -1 Invalid \a fsound
|
||||
*/
|
||||
int fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
|
||||
int next_eos);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <fishsound/decode.h>
|
||||
#include <fishsound/encode.h>
|
||||
#include <fishsound/comments.h>
|
||||
|
||||
#include <fishsound/deprecated.h>
|
||||
|
||||
#endif /* __FISH_SOUND_H__ */
|
47
modules/libfishsound/src/Makefile.in
Normal file
47
modules/libfishsound/src/Makefile.in
Normal file
@ -0,0 +1,47 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = fishsound
|
||||
DIRS = libfishsound
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
58
modules/libfishsound/src/libfishsound/Makefile.in
Normal file
58
modules/libfishsound/src/libfishsound/Makefile.in
Normal file
@ -0,0 +1,58 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = fishsound
|
||||
LIBRARY_NAME = fishsound
|
||||
FORCE_STATIC_LIB= 1
|
||||
|
||||
CSRCS = \
|
||||
fishsound_comments.c \
|
||||
fishsound_decode.c \
|
||||
fishsound.c \
|
||||
fs_vector.c \
|
||||
fishsound_speex.c \
|
||||
fishsound_vorbis.c \
|
||||
fishsound_flac.c \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
106
modules/libfishsound/src/libfishsound/config.h
Normal file
106
modules/libfishsound/src/libfishsound/config.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Do not build decoding support */
|
||||
#define FS_DECODE 1
|
||||
|
||||
/* Do not build encoding support */
|
||||
#define FS_ENCODE 0
|
||||
|
||||
/* Define to build experimental code */
|
||||
/* #undef FS_EXPERIMENTAL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have libFLAC */
|
||||
#define HAVE_FLAC 0
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define if have libsndfile */
|
||||
/* #undef HAVE_LIBSNDFILE1 */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define if have liboggz */
|
||||
/* #undef HAVE_OGGZ */
|
||||
|
||||
/* Define to 1 if you have libspeex */
|
||||
#define HAVE_SPEEX 0
|
||||
|
||||
/* Define to 1 if you have libspeex 1.1.x */
|
||||
/* #undef HAVE_SPEEX_1_1 */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have libvorbis */
|
||||
#define HAVE_VORBIS 1
|
||||
|
||||
/* Define to 1 if you have libvorbisenc */
|
||||
#define HAVE_VORBISENC 0
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libfishsound"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.9.1"
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
#undef FS_ENCODE
|
||||
#define FS_ENCODE 0
|
||||
#undef HAVE_FLAC
|
||||
#define HAVE_FLAC 0
|
||||
#undef HAVE_OGGZ
|
||||
#define HAVE_OGGZ 1
|
||||
#undef HAVE_SPEEX
|
||||
#define HAVE_SPEEX 0
|
||||
#undef HAVE_VORBIS
|
||||
#define HAVE_VORBIS 1
|
||||
#undef HAVE_VORBISENC
|
||||
#define HAVE_VORBISENC 0
|
||||
#undef DEBUG
|
68
modules/libfishsound/src/libfishsound/convert.h
Normal file
68
modules/libfishsound/src/libfishsound/convert.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_CONVERT_H__
|
||||
#define __FISH_SOUND_CONVERT_H__
|
||||
|
||||
/* inline functions */
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave (float ** src, float * dest[],
|
||||
long frames, int channels, float mult_factor)
|
||||
{
|
||||
int i, j;
|
||||
float * d, * s = (float *)src;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = s[i*channels + j] * mult_factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave (float * src[], float ** dest,
|
||||
long frames, int channels, float mult_factor)
|
||||
{
|
||||
int i, j;
|
||||
float * s, * d = (float *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = s[i] * mult_factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __FISH_SOUND_CONVERT_H__ */
|
415
modules/libfishsound/src/libfishsound/convert_c.h
Normal file
415
modules/libfishsound/src/libfishsound/convert_c.h
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_CONVERT_C_H__
|
||||
#define __FISH_SOUND_CONVERT_C_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
/* inline functions */
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_s (short ** src, short * dest[],
|
||||
long frames, int channels)
|
||||
{
|
||||
int i, j;
|
||||
short * d, * s = (short *)src;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = s[i*channels + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_i (short ** src, int * dest[], long frames, int channels)
|
||||
{
|
||||
int i, j;
|
||||
short * s = (short *)src;
|
||||
int * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = (int) s[i*channels + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_f (short ** src, float * dest[], long frames, int channels,
|
||||
float mult)
|
||||
{
|
||||
int i, j;
|
||||
short * s = (short *)src;
|
||||
float * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = ((float) s[i*channels + j]) * mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_d (short ** src, double * dest[], long frames, int channels,
|
||||
double mult)
|
||||
{
|
||||
int i, j;
|
||||
short * s = (short *)src;
|
||||
double * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = ((double) s[i*channels + j]) * mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_s (float ** src, short * dest[],
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s = (float *)src;
|
||||
short * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = (short) (s[i*channels + j] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_i (float ** src, int * dest[],
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s = (float *)src;
|
||||
int * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = (int) (s[i*channels + j] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_f (float ** src, float * dest[],
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s = (float *)src, * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = s[i*channels + j] * mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_d (float ** src, double * dest[],
|
||||
long frames, int channels, double mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s = (float *)src;
|
||||
double * d;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = (double) s[i*channels + j] * mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_f_s (float * src[], short ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s;
|
||||
short * d = (short *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (short) (s[i] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_s_s (short * src[], short ** dest,
|
||||
long frames, int channels)
|
||||
{
|
||||
int i, j;
|
||||
short * s, * d = (short *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_s_f (short * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
short * s;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (float) (s[i] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
|
||||
int ret=x;
|
||||
ret-= ((x<=32767)-1)&(x-32767);
|
||||
ret-= ((x>=-32768)-1)&(x+32768);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_i_s (ogg_int32_t * src[], short ** dest,
|
||||
long frames, int channels, int shift)
|
||||
{
|
||||
int i, j;
|
||||
ogg_int32_t * s;
|
||||
short * d = (short *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (short) CLIP_TO_15(s[i]>>9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_i_f (int * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
int * s;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (float) (s[i] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_f_f (float * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s, * d = (float *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = s[i] * mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_d_s (double * src[], short ** dest,
|
||||
long frames, int channels, double mult)
|
||||
{
|
||||
int i, j;
|
||||
double * s;
|
||||
short * d = (short *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (short) (s[i] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_d_f (double * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
double * s;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (float) s[i] * mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_s (short * src, short * dest, long samples)
|
||||
{
|
||||
memcpy (dest, src, samples * sizeof (short));
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_i (short * src, int * dest, long samples)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (int) src[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_f (short * src, float * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (float) src[i] * mult;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_d (short * src, double * dest, long samples, double mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = ((double)src[i]) * mult;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_i_s (int * src, short * dest, long samples)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (short) src[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_i_f (int * src, float * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (float) src[i] * mult;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_s (float * src, short * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (short) (src[i] * mult);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_i (float * src, int * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (int) (src[i] * mult);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_f (float * src, float * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = src[i] * mult;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_d (float * src, double * dest, long samples, double mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (double)src[i] * mult;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_d_s (double * src, short * dest, long samples, double mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (short) (src[i] * mult);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_d_f (double * src, float * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (float)src[i] * mult;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __FISH_SOUND_CONVERT_C_H__ */
|
393
modules/libfishsound/src/libfishsound/convert_oil.h
Normal file
393
modules/libfishsound/src/libfishsound/convert_oil.h
Normal file
@ -0,0 +1,393 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* David Schleef, ds@schleef.org
|
||||
* January, 2005
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_CONVERT_OIL_H__
|
||||
#define __FISH_SOUND_CONVERT_OIL_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include <liboil/liboil.h>
|
||||
|
||||
/* inline functions */
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_s (short ** src, short * dest[],
|
||||
long frames, int channels)
|
||||
{
|
||||
int j;
|
||||
short * s = (short *)src;
|
||||
|
||||
#define oil_restride_s16(a,b,c,d,e) oil_conv_u16_s16((uint16_t *)a,b,c,d,e)
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_restride_s16 (dest[j], sizeof(short), s + j,
|
||||
channels * sizeof(short), frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_i (short ** src, int * dest[], long frames, int channels)
|
||||
{
|
||||
int j;
|
||||
short * s = (short *)src;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_s32_s16 (dest[j], sizeof(int), s + j,
|
||||
channels * sizeof(short), frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_f (short ** src, float * dest[], long frames, int channels,
|
||||
float mult)
|
||||
{
|
||||
int j;
|
||||
short * s = (short *)src;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_f32_s16 (dest[j], sizeof(float), s + j,
|
||||
channels * sizeof(short), frames);
|
||||
oil_scalarmult_f32 (dest[j], sizeof (float), dest[j], sizeof(float),
|
||||
&mult, frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_s_d (short ** src, double * dest[], long frames, int channels,
|
||||
double mult)
|
||||
{
|
||||
int j;
|
||||
short * s = (short *)src;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_f64_s16 (dest[j], sizeof(double), s + j,
|
||||
channels * sizeof(short), frames);
|
||||
oil_scalarmult_f64 (dest[j], sizeof (double), dest[j], sizeof (double),
|
||||
&mult, frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_s (float ** src, short * dest[],
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s = (float *)src;
|
||||
short * d;
|
||||
|
||||
/* FIXME: this needs a temporary buffer for liboil */
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = (short) (s[i*channels + j] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_i (float ** src, int * dest[],
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s = (float *)src;
|
||||
int * d;
|
||||
|
||||
/* FIXME: this needs a temporary buffer for liboil */
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = dest[j];
|
||||
d[i] = (int) (s[i*channels + j] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_f (float ** src, float * dest[],
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int j;
|
||||
float * s = (float *)src;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_scalarmult_f32 (dest[j], sizeof(float), s + j,
|
||||
channels * sizeof(float), &mult, frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_deinterleave_f_d (float ** src, double * dest[],
|
||||
long frames, int channels, double mult)
|
||||
{
|
||||
int j;
|
||||
float * s = (float *)src;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_f64_f32 (dest[j], sizeof(double), s + j,
|
||||
channels * sizeof(float), frames);
|
||||
oil_scalarmult_f64 (dest[j], sizeof(double), dest[j],
|
||||
sizeof(double), &mult, frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_f_s (float * src[], short ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int i, j;
|
||||
float * s;
|
||||
short * d = (short *)dest;
|
||||
|
||||
/* FIXME: this needs a temporary buffer for liboil */
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (short) (s[i] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_s_s (short * src[], short ** dest,
|
||||
long frames, int channels)
|
||||
{
|
||||
int j;
|
||||
short * d = (short *)dest;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_restride_s16 (d + j, sizeof (short) * channels, src[j],
|
||||
sizeof (short), frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_s_f (short * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int j;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_f32_s16 (d + j, sizeof (float) * channels, src[j],
|
||||
sizeof (short), frames);
|
||||
}
|
||||
oil_scalarmult_f32 (d, sizeof(float), d, sizeof(float), &mult,
|
||||
channels * frames);
|
||||
}
|
||||
|
||||
static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
|
||||
int ret=x;
|
||||
ret-= ((x<=32767)-1)&(x-32767);
|
||||
ret-= ((x>=-32768)-1)&(x+32768);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_i_s (ogg_int32_t * src[], short ** dest,
|
||||
long frames, int channels, int shift)
|
||||
{
|
||||
int i, j;
|
||||
ogg_int32_t * s;
|
||||
short * d = (short *)dest;
|
||||
|
||||
/* FIXME: shouldn't this use shift? */
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (short) CLIP_TO_15(s[i]>>9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_i_f (int * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int j;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_f32_s32 (d + j, sizeof (float) * channels, src[j],
|
||||
sizeof (int), frames);
|
||||
}
|
||||
oil_scalarmult_f32 (d, sizeof(float), d, sizeof(float), &mult,
|
||||
channels * frames);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_f_f (float * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int j;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_scalarmult_f32 (d + j, sizeof (float) * channels, src[j],
|
||||
sizeof (float), &mult, frames);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_d_s (double * src[], short ** dest,
|
||||
long frames, int channels, double mult)
|
||||
{
|
||||
int i, j;
|
||||
double * s;
|
||||
short * d = (short *)dest;
|
||||
|
||||
/* FIXME: needs temporary buffer */
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
s = src[j];
|
||||
d[i*channels + j] = (short) (s[i] * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_interleave_d_f (double * src[], float ** dest,
|
||||
long frames, int channels, float mult)
|
||||
{
|
||||
int j;
|
||||
float * d = (float *)dest;
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
oil_conv_f32_f64 (d + j, sizeof (float) * channels, src[j],
|
||||
sizeof (double), frames);
|
||||
}
|
||||
oil_scalarmult_f32 (d, sizeof(float), d, sizeof(float), &mult,
|
||||
channels * frames);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_s (short * src, short * dest, long samples)
|
||||
{
|
||||
memcpy (dest, src, samples * sizeof (short));
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_i (short * src, int * dest, long samples)
|
||||
{
|
||||
oil_conv_s32_s16 (dest, sizeof(int), src, sizeof(short), samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_f (short * src, float * dest, long samples, float mult)
|
||||
{
|
||||
oil_conv_f32_s16 (dest, sizeof(float), src, sizeof(short), samples);
|
||||
oil_scalarmult_f32 (dest, sizeof(float), dest, sizeof(float), &mult, samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_s_d (short * src, double * dest, long samples, double mult)
|
||||
{
|
||||
oil_conv_f64_s16 (dest, sizeof(double), src, sizeof(short), samples);
|
||||
oil_scalarmult_f64 (dest, sizeof(double), dest, sizeof(double), &mult,
|
||||
samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_i_s (int * src, short * dest, long samples)
|
||||
{
|
||||
/* FIXME: should this clip? */
|
||||
oil_conv_s16_s32 (dest, sizeof(dest), src, sizeof(int), samples);
|
||||
/* oil_clipconv_s16_s32 (dest, sizeof(dest), src, sizeof(int), samples); */
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_i_f (int * src, float * dest, long samples, float mult)
|
||||
{
|
||||
oil_conv_f32_s32 (dest, sizeof(float), src, sizeof(int), samples);
|
||||
oil_scalarmult_f32 (dest, sizeof(float), dest, sizeof(float), &mult, samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_s (float * src, short * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* FIXME: needs temp buffer */
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (short) (src[i] * mult);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_i (float * src, int * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* FIXME: needs temp buffer */
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (int) (src[i] * mult);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_f (float * src, float * dest, long samples, float mult)
|
||||
{
|
||||
oil_scalarmult_f32 (dest, sizeof(float), src, sizeof(float), &mult, samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_f_d (float * src, double * dest, long samples, double mult)
|
||||
{
|
||||
oil_conv_f64_f32 (dest, sizeof(double), src, sizeof(float), samples);
|
||||
oil_scalarmult_f64 (dest, sizeof(double), dest, sizeof(double), &mult, samples);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_d_s (double * src, short * dest, long samples, double mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* FIXME: needs temp buffer */
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (short) (src[i] * mult);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_fs_convert_d_f (double * src, float * dest, long samples, float mult)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* FIXME: needs temp buffer */
|
||||
for (i = 0; i < samples; i++) {
|
||||
dest[i] = (float)src[i] * mult;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __FISH_SOUND_CONVERT_OIL_H__ */
|
253
modules/libfishsound/src/libfishsound/fishsound.c
Normal file
253
modules/libfishsound/src/libfishsound/fishsound.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
int
|
||||
fish_sound_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
if (bytes < 8) return FISH_SOUND_ERR_SHORT_IDENTIFY;
|
||||
|
||||
if (HAVE_VORBIS &&
|
||||
fish_sound_vorbis_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
|
||||
return FISH_SOUND_VORBIS;
|
||||
|
||||
if (HAVE_SPEEX &&
|
||||
fish_sound_speex_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
|
||||
return FISH_SOUND_SPEEX;
|
||||
|
||||
if (fish_sound_flac_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
|
||||
return FISH_SOUND_FLAC;
|
||||
|
||||
return FISH_SOUND_UNKNOWN;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_set_format (FishSound * fsound, int format)
|
||||
{
|
||||
if (format == FISH_SOUND_VORBIS) {
|
||||
fsound->codec = fish_sound_vorbis_codec ();
|
||||
} else if (format == FISH_SOUND_SPEEX) {
|
||||
fsound->codec = fish_sound_speex_codec ();
|
||||
} else if (format == FISH_SOUND_FLAC) {
|
||||
fsound->codec = fish_sound_flac_codec ();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fsound->codec && fsound->codec->init)
|
||||
fsound->codec->init (fsound);
|
||||
|
||||
fsound->info.format = format;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
FishSound *
|
||||
fish_sound_new (int mode, FishSoundInfo * fsinfo)
|
||||
{
|
||||
FishSound * fsound;
|
||||
|
||||
if (!FS_DECODE && mode == FISH_SOUND_DECODE) return NULL;
|
||||
|
||||
if (!FS_ENCODE && mode == FISH_SOUND_ENCODE) return NULL;
|
||||
|
||||
if (mode == FISH_SOUND_ENCODE) {
|
||||
if (fsinfo == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
if (!(HAVE_VORBIS && HAVE_VORBISENC)) {
|
||||
if (fsinfo->format == FISH_SOUND_VORBIS) return NULL;
|
||||
}
|
||||
if (!HAVE_SPEEX) {
|
||||
if (fsinfo->format == FISH_SOUND_SPEEX) return NULL;
|
||||
}
|
||||
if (!HAVE_FLAC) {
|
||||
if (fsinfo->format == FISH_SOUND_FLAC) return NULL;
|
||||
}
|
||||
}
|
||||
} else if (mode != FISH_SOUND_DECODE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fsound = fs_malloc (sizeof (FishSound));
|
||||
|
||||
fsound->mode = mode;
|
||||
fsound->interleave = 0;
|
||||
fsound->frameno = 0;
|
||||
fsound->next_granulepos = -1;
|
||||
fsound->next_eos = 0;
|
||||
fsound->codec = NULL;
|
||||
fsound->codec_data = NULL;
|
||||
fsound->callback.encoded = NULL;
|
||||
fsound->user_data = NULL;
|
||||
|
||||
fish_sound_comments_init (fsound);
|
||||
|
||||
if (mode == FISH_SOUND_DECODE) {
|
||||
fsound->info.samplerate = 0;
|
||||
fsound->info.channels = 0;
|
||||
fsound->info.format = FISH_SOUND_UNKNOWN;
|
||||
} else if (mode == FISH_SOUND_ENCODE) {
|
||||
fsound->info.samplerate = fsinfo->samplerate;
|
||||
fsound->info.channels = fsinfo->channels;
|
||||
fsound->info.format = fsinfo->format;
|
||||
|
||||
if (fish_sound_set_format (fsound, fsinfo->format) == -1) {
|
||||
fs_free (fsound);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
long
|
||||
fish_sound_flush (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
if (fsound->codec && fsound->codec->flush)
|
||||
return fsound->codec->flush (fsound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_reset (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
if (fsound->codec && fsound->codec->reset)
|
||||
return fsound->codec->reset (fsound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FishSound *
|
||||
fish_sound_delete (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return NULL;
|
||||
|
||||
if (fsound->codec && fsound->codec->del)
|
||||
fsound->codec->del (fsound);
|
||||
|
||||
fs_free (fsound->codec);
|
||||
|
||||
fish_sound_comments_free (fsound);
|
||||
|
||||
fs_free (fsound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_command (FishSound * fsound, int command, void * data, int datasize)
|
||||
{
|
||||
FishSoundInfo * fsinfo = (FishSoundInfo *)data;
|
||||
int * pi = (int *)data;
|
||||
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
switch (command) {
|
||||
case FISH_SOUND_GET_INFO:
|
||||
memcpy (fsinfo, &fsound->info, sizeof (FishSoundInfo));
|
||||
break;
|
||||
case FISH_SOUND_GET_INTERLEAVE:
|
||||
*pi = fsound->interleave;
|
||||
break;
|
||||
case FISH_SOUND_SET_INTERLEAVE:
|
||||
fsound->interleave = (*pi ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
if (fsound->codec && fsound->codec->command)
|
||||
return fsound->codec->command (fsound, command, data, datasize);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_get_interleave (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
return fsound->interleave;
|
||||
}
|
||||
|
||||
#ifndef FS_DISABLE_DEPRECATED
|
||||
int
|
||||
fish_sound_set_interleave (FishSound * fsound, int interleave)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
fsound->interleave = (interleave ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
long
|
||||
fish_sound_get_frameno (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return -1L;
|
||||
|
||||
return fsound->frameno;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_set_frameno (FishSound * fsound, long frameno)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
fsound->frameno = frameno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
|
||||
int next_eos)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
fsound->next_granulepos = next_granulepos;
|
||||
fsound->next_eos = next_eos;
|
||||
|
||||
return 0;
|
||||
}
|
594
modules/libfishsound/src/libfishsound/fishsound_comments.c
Normal file
594
modules/libfishsound/src/libfishsound/fishsound_comments.c
Normal file
@ -0,0 +1,594 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
static char *
|
||||
fs_strdup (const char * s)
|
||||
{
|
||||
char * ret;
|
||||
if (s == NULL) return NULL;
|
||||
ret = fs_malloc (strlen(s) + 1);
|
||||
return strcpy (ret, s);
|
||||
}
|
||||
|
||||
static char *
|
||||
fs_strdup_len (const char * s, int len)
|
||||
{
|
||||
char * ret;
|
||||
if (s == NULL) return NULL;
|
||||
if (len == 0) return NULL;
|
||||
ret = fs_malloc (len + 1);
|
||||
if (strncpy (ret, s, len) == NULL) {
|
||||
fs_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret[len] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
fs_index_len (const char * s, char c, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; *s && i < len; i++, s++) {
|
||||
if (*s == c) return (char *)s;
|
||||
}
|
||||
|
||||
if (i < len) return (char *)s;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void comment_init(char **comments, int* length, char *vendor_string);
|
||||
static void comment_add(char **comments, int* length, char *tag, char *val);
|
||||
#endif
|
||||
|
||||
/*
|
||||
Comments will be stored in the Vorbis style.
|
||||
It is describled in the "Structure" section of
|
||||
http://www.xiph.org/ogg/vorbis/doc/v-comment.html
|
||||
|
||||
The comment header is decoded as follows:
|
||||
1) [vendor_length] = read an unsigned integer of 32 bits
|
||||
2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
|
||||
3) [user_comment_list_length] = read an unsigned integer of 32 bits
|
||||
4) iterate [user_comment_list_length] times {
|
||||
5) [length] = read an unsigned integer of 32 bits
|
||||
6) this iteration's user comment = read a UTF-8 vector as [length] octets
|
||||
}
|
||||
7) [framing_bit] = read a single bit as boolean
|
||||
8) if ( [framing_bit] unset or end of packet ) then ERROR
|
||||
9) done.
|
||||
|
||||
If you have troubles, please write to ymnk@jcraft.com.
|
||||
*/
|
||||
|
||||
#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
|
||||
((buf[base+2]<<16)&0xff0000)| \
|
||||
((buf[base+1]<<8)&0xff00)| \
|
||||
(buf[base]&0xff))
|
||||
#define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
|
||||
buf[base+2]=((val)>>16)&0xff; \
|
||||
buf[base+1]=((val)>>8)&0xff; \
|
||||
buf[base]=(val)&0xff; \
|
||||
}while(0)
|
||||
|
||||
#if 0
|
||||
static void
|
||||
comment_init(char **comments, int* length, char *vendor_string)
|
||||
{
|
||||
int vendor_length=strlen(vendor_string);
|
||||
int user_comment_list_length=0;
|
||||
int len=4+vendor_length+4;
|
||||
char *p=(char*)fs_malloc(len);
|
||||
if(p==NULL){
|
||||
}
|
||||
writeint(p, 0, vendor_length);
|
||||
memcpy(p+4, vendor_string, vendor_length);
|
||||
writeint(p, 4+vendor_length, user_comment_list_length);
|
||||
*length=len;
|
||||
*comments=p;
|
||||
}
|
||||
|
||||
static void
|
||||
comment_add(char **comments, int* length, char *tag, char *val)
|
||||
{
|
||||
char* p=*comments;
|
||||
int vendor_length=readint(p, 0);
|
||||
int user_comment_list_length=readint(p, 4+vendor_length);
|
||||
int tag_len=(tag?strlen(tag):0);
|
||||
int val_len=strlen(val);
|
||||
int len=(*length)+4+tag_len+val_len;
|
||||
|
||||
p=(char*)fs_realloc(p, len);
|
||||
if(p==NULL){
|
||||
}
|
||||
|
||||
writeint(p, *length, tag_len+val_len); /* length of comment */
|
||||
if(tag) memcpy(p+*length+4, tag, tag_len); /* comment */
|
||||
memcpy(p+*length+4+tag_len, val, val_len); /* comment */
|
||||
writeint(p, 4+vendor_length, user_comment_list_length+1);
|
||||
|
||||
*comments=p;
|
||||
*length=len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
fs_comment_validate_byname (const char * name, const char * value)
|
||||
{
|
||||
const char * c;
|
||||
|
||||
if (!name || !value) return 0;
|
||||
|
||||
for (c = name; *c; c++) {
|
||||
if (*c < 0x20 || *c > 0x7D || *c == 0x3D) {
|
||||
#ifdef DEBUG
|
||||
printf ("XXX char %c in %s invalid\n", *c, name);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: we really should validate value as UTF-8 here, but ... */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static FishSoundComment *
|
||||
fs_comment_new (const char * name, const char * value)
|
||||
{
|
||||
FishSoundComment * comment;
|
||||
|
||||
if (!fs_comment_validate_byname (name, value)) return NULL;
|
||||
|
||||
comment = fs_malloc (sizeof (FishSoundComment));
|
||||
comment->name = fs_strdup (name);
|
||||
comment->value = fs_strdup (value);
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_comment_free (FishSoundComment * comment)
|
||||
{
|
||||
if (!comment) return;
|
||||
if (comment->name) fs_free (comment->name);
|
||||
if (comment->value) fs_free (comment->value);
|
||||
fs_free (comment);
|
||||
}
|
||||
|
||||
static int
|
||||
fs_comment_cmp (const FishSoundComment * comment1, const FishSoundComment * comment2)
|
||||
{
|
||||
if (comment1 == comment2) return 1;
|
||||
if (!comment1 || !comment2) return 0;
|
||||
|
||||
if (strcasecmp (comment1->name, comment2->name)) return 0;
|
||||
if (strcmp (comment1->value, comment2->value)) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Public API */
|
||||
|
||||
const char *
|
||||
fish_sound_comment_get_vendor (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return NULL;
|
||||
|
||||
return fsound->vendor;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor_string)
|
||||
{
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
if (fsound->vendor) fs_free (fsound->vendor);
|
||||
|
||||
fsound->vendor = fs_strdup (vendor_string);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_first (FishSound * fsound)
|
||||
{
|
||||
if (fsound == NULL) return NULL;
|
||||
|
||||
return fs_vector_nth (fsound->comments, 0);
|
||||
}
|
||||
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_first_byname (FishSound * fsound, char * name)
|
||||
{
|
||||
FishSoundComment * comment;
|
||||
int i;
|
||||
|
||||
if (fsound == NULL) return NULL;
|
||||
|
||||
if (name == NULL) return fs_vector_nth (fsound->comments, 0);
|
||||
|
||||
if (!fs_comment_validate_byname (name, ""))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < fs_vector_size (fsound->comments); i++) {
|
||||
comment = (FishSoundComment *) fs_vector_nth (fsound->comments, i);
|
||||
if (comment->name && !strcasecmp (name, comment->name))
|
||||
return comment;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (fsound == NULL || comment == NULL) return NULL;
|
||||
|
||||
i = fs_vector_find_index (fsound->comments, comment);
|
||||
|
||||
return fs_vector_nth (fsound->comments, i+1);
|
||||
}
|
||||
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_next_byname (FishSound * fsound,
|
||||
const FishSoundComment * comment)
|
||||
{
|
||||
FishSoundComment * v_comment;
|
||||
int i;
|
||||
|
||||
if (fsound == NULL || comment == NULL) return NULL;
|
||||
|
||||
i = fs_vector_find_index (fsound->comments, comment);
|
||||
|
||||
for (i++; i < fs_vector_size (fsound->comments); i++) {
|
||||
v_comment = (FishSoundComment *) fs_vector_nth (fsound->comments, i);
|
||||
if (v_comment->name && !strcasecmp (comment->name, v_comment->name))
|
||||
return v_comment;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define _fs_comment_add(f,c) fs_vector_insert ((f)->comments, (c))
|
||||
|
||||
int
|
||||
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment)
|
||||
{
|
||||
FishSoundComment * new_comment;
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
if (fsound->mode != FISH_SOUND_ENCODE)
|
||||
return FISH_SOUND_ERR_INVALID;
|
||||
|
||||
#if FS_ENCODE
|
||||
if (!fs_comment_validate_byname (comment->name, comment->value))
|
||||
return FISH_SOUND_ERR_COMMENT_INVALID;
|
||||
|
||||
new_comment = fs_comment_new (comment->name, comment->value);
|
||||
|
||||
_fs_comment_add (fsound, new_comment);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
|
||||
const char * value)
|
||||
{
|
||||
FishSoundComment * comment;
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
if (fsound->mode != FISH_SOUND_ENCODE)
|
||||
return FISH_SOUND_ERR_INVALID;
|
||||
|
||||
#if FS_ENCODE
|
||||
if (!fs_comment_validate_byname (name, value))
|
||||
return FISH_SOUND_ERR_COMMENT_INVALID;
|
||||
|
||||
comment = fs_comment_new (name, value);
|
||||
|
||||
_fs_comment_add (fsound, comment);
|
||||
|
||||
return 0;
|
||||
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
|
||||
{
|
||||
FishSoundComment * v_comment;
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
if (fsound->mode != FISH_SOUND_ENCODE)
|
||||
return FISH_SOUND_ERR_INVALID;
|
||||
|
||||
#if FS_ENCODE
|
||||
|
||||
v_comment = fs_vector_find (fsound->comments, comment);
|
||||
|
||||
if (v_comment == NULL) return 0;
|
||||
|
||||
fs_vector_remove (fsound->comments, v_comment);
|
||||
fs_comment_free (v_comment);
|
||||
|
||||
return 1;
|
||||
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_comment_remove_byname (FishSound * fsound, char * name)
|
||||
{
|
||||
FishSoundComment * comment;
|
||||
int i, ret = 0;
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
if (fsound->mode != FISH_SOUND_ENCODE)
|
||||
return FISH_SOUND_ERR_INVALID;
|
||||
|
||||
#if FS_ENCODE
|
||||
for (i = 0; i < fs_vector_size (fsound->comments); i++) {
|
||||
comment = (FishSoundComment *) fs_vector_nth (fsound->comments, i);
|
||||
if (!strcasecmp (name, comment->name)) {
|
||||
fish_sound_comment_remove (fsound, comment);
|
||||
i--;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Internal API */
|
||||
int
|
||||
fish_sound_comments_init (FishSound * fsound)
|
||||
{
|
||||
fsound->vendor = NULL;
|
||||
fsound->comments = fs_vector_new ((FishSoundCmpFunc) fs_comment_cmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_comments_free (FishSound * fsound)
|
||||
{
|
||||
fs_vector_foreach (fsound->comments, (FishSoundFunc)fs_comment_free);
|
||||
fs_vector_delete (fsound->comments);
|
||||
fsound->comments = NULL;
|
||||
|
||||
if (fsound->vendor) fs_free (fsound->vendor);
|
||||
fsound->vendor = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
|
||||
long length)
|
||||
{
|
||||
char *c= (char *)comments;
|
||||
int len, i, nb_fields, n;
|
||||
char *end;
|
||||
char * name, * value, * nvalue = NULL;
|
||||
FishSoundComment * comment;
|
||||
|
||||
if (length<8)
|
||||
return -1;
|
||||
|
||||
end = c+length;
|
||||
len=readint(c, 0);
|
||||
|
||||
c+=4;
|
||||
if (c+len>end) return -1;
|
||||
|
||||
/* Vendor */
|
||||
nvalue = fs_strdup_len (c, len);
|
||||
fish_sound_comment_set_vendor (fsound, nvalue);
|
||||
if (nvalue) fs_free (nvalue);
|
||||
#ifdef DEBUG
|
||||
fwrite(c, 1, len, stderr); fputc ('\n', stderr);
|
||||
#endif
|
||||
c+=len;
|
||||
|
||||
if (c+4>end) return -1;
|
||||
|
||||
nb_fields=readint(c, 0);
|
||||
#ifdef DEBUG
|
||||
printf ("fish_sound_comments_decode: %d comments\n", nb_fields);
|
||||
#endif
|
||||
|
||||
c+=4;
|
||||
for (i=0;i<nb_fields;i++)
|
||||
{
|
||||
if (c+4>end) return -1;
|
||||
|
||||
len=readint(c, 0);
|
||||
#ifdef DEBUG
|
||||
printf ("fish_sound_comments_decode: [%d] len %d\n", i, len);
|
||||
#endif
|
||||
|
||||
c+=4;
|
||||
if (c+len>end) return -1;
|
||||
|
||||
name = c;
|
||||
value = fs_index_len (c, '=', len);
|
||||
if (value) {
|
||||
*value = '\0';
|
||||
value++;
|
||||
|
||||
n = c+len - value;
|
||||
nvalue = fs_strdup_len (value, n);
|
||||
#ifdef DEBUG
|
||||
printf ("fish_sound_comments_decode: %s -> %s (length %d)\n",
|
||||
name, nvalue, n);
|
||||
#endif
|
||||
comment = fs_comment_new (name, nvalue);
|
||||
_fs_comment_add (fsound, comment);
|
||||
fs_free (nvalue);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printf ("fish_sound_comments_decode: [%d] %s (no value)\n",
|
||||
i, name, len);
|
||||
#endif
|
||||
nvalue = fs_strdup_len (name, len);
|
||||
comment = fs_comment_new (nvalue, NULL);
|
||||
_fs_comment_add (fsound, comment);
|
||||
fs_free (nvalue);
|
||||
}
|
||||
|
||||
c+=len;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("fish_sound_comments_decode: done\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
|
||||
long length)
|
||||
{
|
||||
char * c = (char *)buf;
|
||||
const FishSoundComment * comment;
|
||||
int nb_fields = 0, vendor_length, field_length;
|
||||
long actual_length, remaining = length;
|
||||
|
||||
/* Vendor string */
|
||||
vendor_length = strlen (fsound->vendor);
|
||||
actual_length = 4 + vendor_length;
|
||||
|
||||
/* user comment list length */
|
||||
actual_length += 4;
|
||||
|
||||
for (comment = fish_sound_comment_first (fsound); comment;
|
||||
comment = fish_sound_comment_next (fsound, comment)) {
|
||||
actual_length += 4 + strlen (comment->name); /* [size]"name" */
|
||||
if (comment->value)
|
||||
actual_length += 1 + strlen (comment->value); /* "=value" */
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("fish_sound_comments_encode: %s = %s\n",
|
||||
comment->name, comment->value);
|
||||
#endif
|
||||
|
||||
nb_fields++;
|
||||
}
|
||||
|
||||
actual_length++; /* framing bit */
|
||||
|
||||
if (buf == NULL) return actual_length;
|
||||
|
||||
remaining -= 4;
|
||||
if (remaining <= 0) return actual_length;
|
||||
writeint (c, 0, vendor_length);
|
||||
c += 4;
|
||||
|
||||
field_length = strlen (fsound->vendor);
|
||||
memcpy (c, fsound->vendor, MIN (field_length, remaining));
|
||||
c += field_length; remaining -= field_length;
|
||||
if (remaining <= 0 ) return actual_length;
|
||||
|
||||
remaining -= 4;
|
||||
if (remaining <= 0) return actual_length;
|
||||
writeint (c, 0, nb_fields);
|
||||
c += 4;
|
||||
|
||||
for (comment = fish_sound_comment_first (fsound); comment;
|
||||
comment = fish_sound_comment_next (fsound, comment)) {
|
||||
|
||||
field_length = strlen (comment->name); /* [size]"name" */
|
||||
if (comment->value)
|
||||
field_length += 1 + strlen (comment->value); /* "=value" */
|
||||
|
||||
remaining -= 4;
|
||||
if (remaining <= 0) return actual_length;
|
||||
writeint (c, 0, field_length);
|
||||
c += 4;
|
||||
|
||||
field_length = strlen (comment->name);
|
||||
memcpy (c, comment->name, MIN (field_length, remaining));
|
||||
c += field_length; remaining -= field_length;
|
||||
if (remaining <= 0) return actual_length;
|
||||
|
||||
if (comment->value) {
|
||||
remaining --;
|
||||
if (remaining <= 0) return actual_length;
|
||||
*c = '=';
|
||||
c++;
|
||||
|
||||
field_length = strlen (comment->value);
|
||||
memcpy (c, comment->value, MIN (field_length, remaining));
|
||||
c += field_length; remaining -= field_length;
|
||||
if (remaining <= 0) return actual_length;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining <= 0) return actual_length;
|
||||
*c = 0x01;
|
||||
|
||||
return actual_length;
|
||||
}
|
136
modules/libfishsound/src/libfishsound/fishsound_decode.c
Normal file
136
modules/libfishsound/src/libfishsound/fishsound_decode.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
static int
|
||||
fs_decode_update (FishSound * fsound, int interleave)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fsound->codec && fsound->codec->update)
|
||||
ret = fsound->codec->update (fsound, interleave);
|
||||
|
||||
if (ret >= 0) {
|
||||
fsound->interleave = interleave;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fish_sound_set_decoded_float (FishSound * fsound,
|
||||
FishSoundDecoded_Float decoded,
|
||||
void * user_data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_DECODE
|
||||
ret = fs_decode_update (fsound, 0);
|
||||
|
||||
if (ret >= 0) {
|
||||
fsound->callback.decoded_float = decoded;
|
||||
fsound->user_data = user_data;
|
||||
}
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fish_sound_set_decoded_float_ilv (FishSound * fsound,
|
||||
FishSoundDecoded_FloatIlv decoded,
|
||||
void * user_data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_DECODE
|
||||
ret = fs_decode_update (fsound, 1);
|
||||
|
||||
if (ret >= 0) {
|
||||
fsound->callback.decoded_float_ilv = decoded;
|
||||
fsound->user_data = user_data;
|
||||
}
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long
|
||||
fish_sound_decode (FishSound * fsound, unsigned char * buf, long bytes)
|
||||
{
|
||||
int format;
|
||||
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_DECODE
|
||||
if (fsound->info.format == FISH_SOUND_UNKNOWN) {
|
||||
format = fish_sound_identify (buf, bytes);
|
||||
if (format == FISH_SOUND_UNKNOWN) return -1;
|
||||
|
||||
fish_sound_set_format (fsound, format);
|
||||
}
|
||||
|
||||
/*printf ("format: %s\n", fsound->codec->format->name);*/
|
||||
|
||||
if (fsound->codec && fsound->codec->decode)
|
||||
return fsound->codec->decode (fsound, buf, bytes);
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
int fish_sound_set_decoded_callback (FishSound * fsound,
|
||||
FishSoundDecoded_Float decoded,
|
||||
void * user_data)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
return fsound->interleave ?
|
||||
fish_sound_set_decoded_float_ilv (fsound, decoded, user_data) :
|
||||
fish_sound_set_decoded_float (fsound, decoded, user_data);
|
||||
}
|
106
modules/libfishsound/src/libfishsound/fishsound_encode.c
Normal file
106
modules/libfishsound/src/libfishsound/fishsound_encode.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
int
|
||||
fish_sound_set_encoded_callback (FishSound * fsound,
|
||||
FishSoundEncoded encoded,
|
||||
void * user_data)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_ENCODE
|
||||
fsound->callback.encoded = (void *)encoded;
|
||||
fsound->user_data = user_data;
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long fish_sound_encode_float (FishSound * fsound, float * pcm[], long frames)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_ENCODE
|
||||
if (fsound->codec && fsound->codec->encode_f)
|
||||
return fsound->codec->encode_f (fsound, pcm, frames);
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long fish_sound_encode_float_ilv (FishSound * fsound, float ** pcm,
|
||||
long frames)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_ENCODE
|
||||
if (fsound->codec && fsound->codec->encode_f_ilv)
|
||||
return fsound->codec->encode_f_ilv (fsound, pcm, frames);
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FS_DISABLE_DEPRECATED
|
||||
long
|
||||
fish_sound_encode (FishSound * fsound, float ** pcm, long frames)
|
||||
{
|
||||
if (fsound == NULL) return -1;
|
||||
|
||||
#if FS_ENCODE
|
||||
if (fsound->interleave) {
|
||||
if (fsound->codec && fsound->codec->encode_f_ilv)
|
||||
return fsound->codec->encode_f_ilv (fsound, pcm, frames);
|
||||
} else {
|
||||
if (fsound->codec && fsound->codec->encode_f)
|
||||
return fsound->codec->encode_f (fsound, pcm, frames);
|
||||
}
|
||||
#else
|
||||
return FISH_SOUND_ERR_DISABLED;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DEPRECATED */
|
773
modules/libfishsound/src/libfishsound/fishsound_flac.c
Normal file
773
modules/libfishsound/src/libfishsound/fishsound_flac.c
Normal file
@ -0,0 +1,773 @@
|
||||
/*
|
||||
Copyright (C) 2007 Annodex Association
|
||||
|
||||
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 Annodex Association 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 ASSOCIATION 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.
|
||||
*/
|
||||
|
||||
/* Original patches by Tobias Gehrig, 2005
|
||||
* http://www.annodex.net/software/libfishsound/libfishsound-flac/
|
||||
*
|
||||
* The Ogg FLAC mapping is documented in:
|
||||
* http://flac.sourceforge.net/ogg_mapping.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "convert.h"
|
||||
|
||||
/*#define DEBUG*/
|
||||
/*#define DEBUG_VERBOSE*/
|
||||
|
||||
#if HAVE_FLAC
|
||||
|
||||
#include "FLAC/all.h"
|
||||
|
||||
#define BITS_PER_SAMPLE 24
|
||||
|
||||
typedef struct _FishSoundFlacInfo {
|
||||
FLAC__StreamDecoder *fsd;
|
||||
FLAC__StreamEncoder *fse;
|
||||
unsigned char * buffer;
|
||||
char header;
|
||||
long bufferlength;
|
||||
unsigned long packetno;
|
||||
struct {
|
||||
unsigned char major, minor;
|
||||
} version;
|
||||
unsigned short header_packets;
|
||||
void * ipcm;
|
||||
#if FS_DECODE
|
||||
float * pcm_out[8]; /* non-interleaved pcm, output (decode only);
|
||||
* FLAC does max 8 channels */
|
||||
#endif
|
||||
#if FS_ENCODE
|
||||
FLAC__StreamMetadata * enc_vc_metadata; /* FLAC metadata structure for
|
||||
* vorbiscomments (encode only) */
|
||||
#endif
|
||||
} FishSoundFlacInfo;
|
||||
|
||||
int
|
||||
fish_sound_flac_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
if (bytes < 8) return FISH_SOUND_UNKNOWN;
|
||||
if (buf[0] != 0x7f) return FISH_SOUND_UNKNOWN;
|
||||
if (!strncmp ((char *)buf+1, "FLAC", 4)) {
|
||||
#ifdef DEBUG
|
||||
printf("fish_sound_flac_identify: flac found\n");
|
||||
#endif
|
||||
/* if only a short buffer was passed, do a weak identify */
|
||||
if (bytes == 8) return FISH_SOUND_FLAC;
|
||||
|
||||
/* otherwise, look for the fLaC header preceding STREAMINFO */
|
||||
if (!strncmp ((char *)buf+9, "fLaC", 4)) {
|
||||
return FISH_SOUND_FLAC;
|
||||
}
|
||||
}
|
||||
|
||||
return FISH_SOUND_UNKNOWN;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_flac_command (FishSound * fsound, int command, void * data, int datasize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if FS_DECODE
|
||||
static FLAC__StreamDecoderReadStatus
|
||||
fs_flac_read_callback(const FLAC__StreamDecoder *decoder,
|
||||
FLAC__byte buffer[], unsigned *bytes,
|
||||
void *client_data)
|
||||
{
|
||||
FishSound* fsound = (FishSound*)client_data;
|
||||
FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("fs_flac_read_callback: IN\n");
|
||||
#endif
|
||||
if (fi->bufferlength > *bytes) {
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_read_callback: too much data\n");
|
||||
#endif
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
} else if (fi->bufferlength < 1) {
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_read_callback: no data, %ld\n",fi->bufferlength);
|
||||
#endif
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
}
|
||||
|
||||
memcpy(buffer, fi->buffer, fi->bufferlength);
|
||||
*bytes = fi->bufferlength;
|
||||
fi->bufferlength = 0;
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus
|
||||
fs_flac_write_callback(const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__Frame *frame,
|
||||
const FLAC__int32 * const buffer[],
|
||||
void *client_data)
|
||||
{
|
||||
FishSound* fsound = (FishSound*)client_data;
|
||||
FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
|
||||
int i, j, channels, blocksize, offset;
|
||||
|
||||
channels = frame->header.channels;
|
||||
blocksize = frame->header.blocksize;
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("fs_flac_write_callback: IN, blocksize %d\n", blocksize);
|
||||
#endif
|
||||
|
||||
fsound->frameno += blocksize;
|
||||
|
||||
if (fsound->callback.decoded_float) {
|
||||
float norm = 1.0 / ((1 << (frame->header.bits_per_sample - 1)));
|
||||
|
||||
if (fsound->interleave) {
|
||||
FishSoundDecoded_FloatIlv dfi;
|
||||
float* retpcm;
|
||||
|
||||
fi->ipcm = realloc(fi->ipcm, sizeof(float) * channels * blocksize);
|
||||
retpcm = (float*) fi->ipcm;
|
||||
for (i = 0; i < blocksize; i++) {
|
||||
offset = i * channels;
|
||||
for (j = 0; j < channels; j++)
|
||||
retpcm[offset + j] = buffer[j][i] * norm;
|
||||
}
|
||||
dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
|
||||
dfi (fsound, (float **)retpcm, blocksize, fsound->user_data);
|
||||
} else {
|
||||
FishSoundDecoded_Float df;
|
||||
FLAC__int32 * s = (FLAC__int32 *)buffer; /* de-interleave source */
|
||||
float *d; /* de-interleave dest */
|
||||
|
||||
for (j = 0; j < channels; j++) {
|
||||
fi->pcm_out[j] = realloc(fi->pcm_out[j], sizeof(float) * blocksize);
|
||||
}
|
||||
for (i = 0; i < blocksize; i++)
|
||||
for (j = 0; j < channels; j++) {
|
||||
d = fi->pcm_out[j];
|
||||
d[i] = s[i*channels + j] * norm;
|
||||
}
|
||||
df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
|
||||
df (fsound, fi->pcm_out, blocksize, fsound->user_data);
|
||||
}
|
||||
}
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_flac_meta_callback(const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__StreamMetadata *metadata,
|
||||
void *client_data)
|
||||
{
|
||||
FishSound* fsound = (FishSound*)client_data;
|
||||
/* FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data; */
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_meta_callback: IN\n");
|
||||
#endif
|
||||
switch (metadata->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_meta_callback: channels %d, samplerate %d\n",
|
||||
metadata->data.stream_info.channels,
|
||||
metadata->data.stream_info.sample_rate);
|
||||
#endif
|
||||
fsound->info.channels = metadata->data.stream_info.channels;
|
||||
fsound->info.samplerate = metadata->data.stream_info.sample_rate;
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_meta_callback: not yet implemented type\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fs_flac_error_callback(const FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderErrorStatus status,
|
||||
void *client_data)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_error_callback: IN\n");
|
||||
#endif
|
||||
fprintf(stderr, "FLAC ERROR: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
|
||||
}
|
||||
#endif
|
||||
#if FS_DECODE
|
||||
static void*
|
||||
fs_flac_decode_header (FishSound * fsound, unsigned char *buf, long bytes)
|
||||
{
|
||||
FishSoundFlacInfo *fi = fsound->codec_data;
|
||||
if (buf[0] != 0x7f) return NULL;
|
||||
if (strncmp((char *)buf+1, "FLAC", 4) != 0) return NULL;
|
||||
fi->version.major = buf[5];
|
||||
fi->version.minor = buf[6];
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_decode_header : Flac Ogg Mapping Version: %d.%d\n",
|
||||
fi->version.major, fi->version.minor);
|
||||
#endif
|
||||
fi->header_packets = buf[7] << 8 | buf[8];
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_decode_header: Number of Header packets: %d\n",
|
||||
fi->header_packets);
|
||||
#endif
|
||||
|
||||
if ((fi->fsd = FLAC__stream_decoder_new()) == NULL) {
|
||||
#ifdef DEBUG
|
||||
printf ("fs_flac_decode_header: unable to create new stream_decoder\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLAC__stream_decoder_set_read_callback(fi->fsd, fs_flac_read_callback);
|
||||
FLAC__stream_decoder_set_write_callback(fi->fsd, fs_flac_write_callback);
|
||||
FLAC__stream_decoder_set_metadata_callback(fi->fsd, fs_flac_meta_callback);
|
||||
FLAC__stream_decoder_set_error_callback(fi->fsd, fs_flac_error_callback);
|
||||
FLAC__stream_decoder_set_client_data(fi->fsd, fsound);
|
||||
|
||||
if (FLAC__stream_decoder_init(fi->fsd) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
|
||||
return NULL;
|
||||
|
||||
return fi->fsd;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_flac_decode (FishSound * fsound, unsigned char * buf, long bytes)
|
||||
{
|
||||
FishSoundFlacInfo *fi = fsound->codec_data;
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("fs_flac_decode: IN, fi->packetno = %ld\n", fi->packetno);
|
||||
#endif
|
||||
|
||||
if (fi->packetno == 0) {
|
||||
if (fs_flac_decode_header (fsound, buf, bytes) == NULL) {
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_decode: Error reading header\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
fi->buffer = fs_malloc(sizeof(unsigned char)*bytes);
|
||||
memcpy(fi->buffer, buf+9, bytes-9);
|
||||
fi->bufferlength = bytes-9;
|
||||
}
|
||||
else if (fi->packetno <= fi->header_packets){
|
||||
unsigned char* tmp = fs_malloc(sizeof(unsigned char)*(fi->bufferlength+bytes));
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_decode: handling header (fi->header_packets = %d)\n",
|
||||
fi->header_packets);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (fi->packetno == 1) fish_sound_comments_decode (fsound, buf, bytes);
|
||||
#endif
|
||||
|
||||
if ((buf[0] & 0x7) == 4) {
|
||||
int len = (buf[1]<<16) + (buf[2]<<8) + buf[3];
|
||||
#ifdef DEBUG
|
||||
printf ("fs_flac_decode: got vorbiscomments len %d\n", len);
|
||||
#endif
|
||||
fish_sound_comments_decode (fsound, buf+4, len);
|
||||
}
|
||||
|
||||
memcpy(tmp, fi->buffer, fi->bufferlength);
|
||||
memcpy(tmp+fi->bufferlength, buf, bytes);
|
||||
fi->bufferlength += bytes;
|
||||
fs_free(fi->buffer);
|
||||
fi->buffer = tmp;
|
||||
if (fi->packetno == fi->header_packets) {
|
||||
FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd);
|
||||
fs_free(fi->buffer);
|
||||
}
|
||||
} else {
|
||||
fi->buffer = buf;
|
||||
fi->bufferlength = bytes;
|
||||
FLAC__stream_decoder_process_single(fi->fsd);
|
||||
}
|
||||
fi->packetno++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !FS_DECODE */
|
||||
|
||||
#define fs_flac_decode NULL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if FS_ENCODE
|
||||
static FLAC__StreamEncoderWriteStatus
|
||||
fs_flac_enc_write_callback(const FLAC__StreamEncoder *encoder,
|
||||
const FLAC__byte buffer[], unsigned bytes,
|
||||
unsigned samples, unsigned current_frame,
|
||||
void *client_data)
|
||||
{
|
||||
FishSound* fsound = (FishSound*)client_data;
|
||||
FishSoundFlacInfo *fi = fsound->codec_data;
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_enc_write_callback: IN\n");
|
||||
printf("fs_flac_enc_write_callback: bytes: %d, samples: %d\n", bytes, samples);
|
||||
#endif
|
||||
if (fsound->callback.encoded) {
|
||||
FishSoundEncoded encoded = (FishSoundEncoded) fsound->callback.encoded;
|
||||
if (fi->packetno == 0 && fi->header <= 1) {
|
||||
if (fi->header == 0) {
|
||||
/* libFLAC has called us with data containing the normal fLaC header
|
||||
* and a STREAMINFO block. Prepend the FLAC Ogg mapping header,
|
||||
* as described in http://flac.sourceforge.net/ogg_mapping.html.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_enc_write_callback: generating FLAC header packet: "
|
||||
"%c%c%c%c\n", buffer[0], buffer[1], buffer[2], buffer[3]);
|
||||
#endif
|
||||
fi->buffer = (unsigned char*)malloc(sizeof(unsigned char)*(bytes+9));
|
||||
fi->buffer[0] = 0x7f;
|
||||
fi->buffer[1] = 0x46; /* 'F' */
|
||||
fi->buffer[2] = 0x4c; /* 'L' */
|
||||
fi->buffer[3] = 0x41; /* 'A' */
|
||||
fi->buffer[4] = 0x43; /* 'C' */
|
||||
fi->buffer[5] = 1; /* Version major generated by this file */
|
||||
fi->buffer[6] = 0; /* Version minor generated by this file */
|
||||
fi->buffer[7] = 0; /* MSB(be): Nr. other non-audio header packets */
|
||||
fi->buffer[8] = 1; /* LSB(be): Nr. other non-audio header packets */
|
||||
memcpy (fi->buffer+9, buffer, bytes); /* fLaC header ++ STREAMINFO */
|
||||
fi->bufferlength = bytes+9;
|
||||
|
||||
fi->header++;
|
||||
} else {
|
||||
/* Make a temporary copy of the metadata header to pass to the user
|
||||
* callback.
|
||||
*/
|
||||
unsigned char* tmp = (unsigned char*)malloc(sizeof(unsigned char)*(bytes+fi->bufferlength));
|
||||
memcpy (tmp, fi->buffer, fi->bufferlength);
|
||||
memcpy (tmp+fi->bufferlength, buffer, bytes);
|
||||
fs_free(fi->buffer);
|
||||
fi->buffer = tmp;
|
||||
fi->bufferlength += bytes;
|
||||
fi->header++;
|
||||
encoded (fsound, (unsigned char *)fi->buffer, (long)fi->bufferlength,
|
||||
fsound->user_data);
|
||||
}
|
||||
} else {
|
||||
fsound->frameno += samples;
|
||||
encoded (fsound, (unsigned char *)buffer, (long)bytes,
|
||||
fsound->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_flac_enc_meta_callback(const FLAC__StreamEncoder *encoder,
|
||||
const FLAC__StreamMetadata *metadata,
|
||||
void *client_data)
|
||||
{
|
||||
/* FishSound* fsound = (FishSound*)client_data; */
|
||||
/* FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data; */
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_enc_meta_callback: IN\n");
|
||||
#endif
|
||||
switch (metadata->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_enc_meta_callback: channels %d, samplerate %d\n",
|
||||
metadata->data.stream_info.channels,
|
||||
metadata->data.stream_info.sample_rate);
|
||||
#endif
|
||||
/*
|
||||
fsound->info.channels = metadata->data.stream_info.channels;
|
||||
fsound->info.samplerate = metadata->data.stream_info.sample_rate;
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_enc_meta_callback: metadata type not yet implemented\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a local alias for an unwieldy type name */
|
||||
typedef FLAC__StreamMetadata_VorbisComment_Entry FLAC__VCEntry;
|
||||
|
||||
static void
|
||||
fs_flac_metadata_free (FLAC__StreamMetadata * metadata)
|
||||
{
|
||||
unsigned int i, length;
|
||||
FLAC__VCEntry * comments;
|
||||
|
||||
if (metadata == NULL) return;
|
||||
|
||||
length = metadata->data.vorbis_comment.num_comments;
|
||||
comments = metadata->data.vorbis_comment.comments;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
fs_free (comments[i].entry);
|
||||
}
|
||||
|
||||
fs_free (comments);
|
||||
fs_free (metadata);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static FLAC__byte *
|
||||
fs_flac_encode_vcentry (const FishSoundComment * comment)
|
||||
{
|
||||
FLAC__byte * entry;
|
||||
FLAC__uint32 length;
|
||||
size_t name_len=0, value_len=0;
|
||||
|
||||
name_len = strlen(comment->name);
|
||||
length = name_len + 1;
|
||||
|
||||
if (comment->value) {
|
||||
value_len = strlen (comment->value);
|
||||
length += value_len + 1;
|
||||
}
|
||||
|
||||
entry = fs_malloc (length);
|
||||
|
||||
/* We assume that comment->name, value are NUL terminated, as they were
|
||||
* produced by our own comments.c */
|
||||
strcpy ((char *)entry, comment->name);
|
||||
|
||||
if (comment->value) {
|
||||
entry[name_len] = '=';
|
||||
strcpy ((char *)&entry[name_len+1], comment->value);
|
||||
}
|
||||
|
||||
entry[length-1] = '\0';
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static FLAC__StreamMetadata *
|
||||
fs_flac_encode_vorbiscomments (FishSound * fsound)
|
||||
{
|
||||
FishSoundFlacInfo * fi = fsound->codec_data;
|
||||
FLAC__StreamMetadata * metadata;
|
||||
const FishSoundComment * comment;
|
||||
unsigned int i=0, length=0, total_length;
|
||||
FLAC__VCEntry * comments;
|
||||
|
||||
/* libFLAC seems to require us to know the total length of the generated
|
||||
* vorbiscomment packet, even though it will silently generate the
|
||||
* vendor string. Hence, this value was determined by inspection for
|
||||
* the version "reference libFLAC 1.1.2"
|
||||
*/
|
||||
total_length = 40;
|
||||
|
||||
/* Count the number of comments */
|
||||
for (comment = fish_sound_comment_first (fsound); comment;
|
||||
comment = fish_sound_comment_next (fsound, comment)) {
|
||||
length++;
|
||||
}
|
||||
|
||||
if (length == 0) return NULL;
|
||||
|
||||
comments = (FLAC__VCEntry *)fs_malloc (sizeof(FLAC__VCEntry) * length);
|
||||
|
||||
for (comment = fish_sound_comment_first (fsound); comment;
|
||||
comment = fish_sound_comment_next (fsound, comment)) {
|
||||
comments[i].entry = fs_flac_encode_vcentry (comment);
|
||||
comments[i].length = strlen((char *)comments[i].entry);
|
||||
|
||||
/* In the generated vorbiscomment data, each entry is preceded by a
|
||||
* 32bit length specifier. */
|
||||
total_length += 4 + comments[i].length;
|
||||
i++;
|
||||
}
|
||||
|
||||
metadata = (FLAC__StreamMetadata *) fs_malloc (sizeof (*metadata));
|
||||
metadata->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
|
||||
metadata->is_last = true;
|
||||
metadata->length = total_length;
|
||||
/* Don't bother setting the vendor_string, as libFLAC ignores it */
|
||||
metadata->data.vorbis_comment.num_comments = length;
|
||||
metadata->data.vorbis_comment.comments = comments;
|
||||
|
||||
/* Remember the allocated metadata */
|
||||
fi->enc_vc_metadata = metadata;
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_flac_enc_headers (FishSound * fsound)
|
||||
{
|
||||
FishSoundFlacInfo * fi = fsound->codec_data;
|
||||
FLAC__StreamMetadata * metadata;
|
||||
|
||||
fi->fse = FLAC__stream_encoder_new();
|
||||
FLAC__stream_encoder_set_channels(fi->fse, fsound->info.channels);
|
||||
FLAC__stream_encoder_set_sample_rate(fi->fse, fsound->info.samplerate);
|
||||
FLAC__stream_encoder_set_bits_per_sample(fi->fse, BITS_PER_SAMPLE);
|
||||
FLAC__stream_encoder_set_write_callback(fi->fse, fs_flac_enc_write_callback);
|
||||
FLAC__stream_encoder_set_metadata_callback(fi->fse, fs_flac_enc_meta_callback);
|
||||
FLAC__stream_encoder_set_client_data(fi->fse, fsound);
|
||||
|
||||
metadata = fs_flac_encode_vorbiscomments (fsound);
|
||||
if (metadata != NULL)
|
||||
FLAC__stream_encoder_set_metadata (fi->fse, &metadata, 1);
|
||||
|
||||
/* FLAC__stream_encoder_set_total_samples_estimate(fi->fse, ...);*/
|
||||
if (FLAC__stream_encoder_init(fi->fse) != FLAC__STREAM_ENCODER_OK)
|
||||
return NULL;
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_flac_encode_f (FishSound * fsound, float * pcm[], long frames)
|
||||
{
|
||||
FishSoundFlacInfo *fi = fsound->codec_data;
|
||||
FLAC__int32 *buffer;
|
||||
float * p, norm = (1 << (BITS_PER_SAMPLE - 1));
|
||||
long i;
|
||||
int j, channels = fsound->info.channels;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_encode_f: IN, frames = %ld\n", frames);
|
||||
#endif
|
||||
|
||||
fi->ipcm = realloc(fi->ipcm, sizeof(FLAC__int32) * channels * frames);
|
||||
buffer = (FLAC__int32*) fi->ipcm;
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (j = 0; j < channels; j++) {
|
||||
p = pcm[j];
|
||||
buffer[i*channels + j] = (FLAC__int32) (p[i] * norm);
|
||||
}
|
||||
}
|
||||
|
||||
if (fi->packetno == 0)
|
||||
fs_flac_enc_headers (fsound);
|
||||
|
||||
/* We could have used FLAC__stream_encoder_process() and a more direct
|
||||
* conversion loop above, rather than converting and interleaving. */
|
||||
FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames);
|
||||
|
||||
fi->packetno++;
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_flac_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
|
||||
{
|
||||
FishSoundFlacInfo *fi = fsound->codec_data;
|
||||
FLAC__int32 *buffer;
|
||||
float * p = (float*)pcm, norm = (1 << (BITS_PER_SAMPLE - 1));
|
||||
long i, length = frames * fsound->info.channels;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_encode_f_ilv: IN, frames = %ld\n", frames);
|
||||
#endif
|
||||
|
||||
fi->ipcm = realloc(fi->ipcm, sizeof(FLAC__int32)*fsound->info.channels*frames);
|
||||
buffer = (FLAC__int32*) fi->ipcm;
|
||||
for (i=0; i<length; i++)
|
||||
buffer[i] = p[i] * norm;
|
||||
|
||||
if (fi->packetno == 0)
|
||||
fs_flac_enc_headers (fsound);
|
||||
|
||||
FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames);
|
||||
|
||||
fi->packetno++;
|
||||
|
||||
return frames;
|
||||
}
|
||||
#else /* ! FS_ENCODE */
|
||||
|
||||
#define fs_flac_encode_f NULL
|
||||
#define fs_flac_encode_f_ilv NULL
|
||||
|
||||
#endif /* ! FS_ENCODE */
|
||||
|
||||
|
||||
static FishSound *
|
||||
fs_flac_delete (FishSound * fsound)
|
||||
{
|
||||
FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_delete: IN\n");
|
||||
#endif
|
||||
|
||||
if (fsound->mode == FISH_SOUND_DECODE) {
|
||||
if (fi->fsd) {
|
||||
FLAC__stream_decoder_finish(fi->fsd);
|
||||
FLAC__stream_decoder_delete(fi->fsd);
|
||||
}
|
||||
} else if (fsound->mode == FISH_SOUND_ENCODE) {
|
||||
if (fi->fse) {
|
||||
FLAC__stream_encoder_finish(fi->fse);
|
||||
FLAC__stream_encoder_delete(fi->fse);
|
||||
}
|
||||
if (fi->buffer) {
|
||||
fs_free(fi->buffer);
|
||||
fi->buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (fi->ipcm) fs_free(fi->ipcm);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (fi->pcm_out[i]) fs_free (fi->pcm_out[i]);
|
||||
}
|
||||
|
||||
#if FS_ENCODE
|
||||
if (fi->enc_vc_metadata) {
|
||||
fs_flac_metadata_free (fi->enc_vc_metadata);
|
||||
}
|
||||
#endif
|
||||
|
||||
fs_free (fi);
|
||||
fsound->codec_data = NULL;
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_flac_update (FishSound * fsound, int interleave)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_flac_reset (FishSound * fsound)
|
||||
{
|
||||
/*FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;*/
|
||||
#if 0
|
||||
if (fsound->mode == FISH_SOUND_DECODE) {
|
||||
FLAC__stream_decoder_reset(fi->fsd);
|
||||
} else if (fsound->mode == FISH_SOUND_ENCODE) {
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_flac_flush (FishSound * fsound)
|
||||
{
|
||||
FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("fs_flac_flush: IN (%s)\n",
|
||||
fsound->mode == FISH_SOUND_DECODE ? "decode" : "encode");
|
||||
#endif
|
||||
|
||||
if (fsound->mode == FISH_SOUND_DECODE) {
|
||||
FLAC__stream_decoder_finish(fi->fsd);
|
||||
} else if (fsound->mode == FISH_SOUND_ENCODE) {
|
||||
FLAC__stream_encoder_finish(fi->fse);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_flac_init (FishSound * fsound)
|
||||
{
|
||||
FishSoundFlacInfo *fi;
|
||||
int i;
|
||||
|
||||
fi = fs_malloc (sizeof (FishSoundFlacInfo));
|
||||
if (fi == NULL) return NULL;
|
||||
fi->fsd = NULL;
|
||||
fi->fse = NULL;
|
||||
fi->buffer = NULL;
|
||||
fi->packetno = 0;
|
||||
fi->header = 0;
|
||||
fi->header_packets = 0;
|
||||
|
||||
fi->ipcm = NULL;
|
||||
for (i = 0; i < 8; i++) {
|
||||
fi->pcm_out[i] = NULL;
|
||||
}
|
||||
|
||||
#if FS_ENCODE
|
||||
fi->enc_vc_metadata = NULL;
|
||||
#endif
|
||||
|
||||
fsound->codec_data = fi;
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
FishSoundCodec *
|
||||
fish_sound_flac_codec (void)
|
||||
{
|
||||
FishSoundCodec * codec;
|
||||
|
||||
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
|
||||
|
||||
codec->format.format = FISH_SOUND_FLAC;
|
||||
codec->format.name = "Flac (Xiph.Org)";
|
||||
codec->format.extension = "ogg";
|
||||
|
||||
codec->init = fs_flac_init;
|
||||
codec->del = fs_flac_delete;
|
||||
codec->reset = fs_flac_reset;
|
||||
codec->update = fs_flac_update;
|
||||
codec->command = fs_flac_command;
|
||||
codec->decode = fs_flac_decode;
|
||||
codec->encode_f = fs_flac_encode_f;
|
||||
codec->encode_f_ilv = fs_flac_encode_f_ilv;
|
||||
codec->flush = fs_flac_flush;
|
||||
|
||||
return codec;
|
||||
}
|
||||
|
||||
#else /* !HAVE_FLAC */
|
||||
|
||||
int
|
||||
fish_sound_flac_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
return FISH_SOUND_UNKNOWN;
|
||||
}
|
||||
|
||||
FishSoundCodec *
|
||||
fish_sound_flac_codec (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
730
modules/libfishsound/src/libfishsound/fishsound_speex.c
Normal file
730
modules/libfishsound/src/libfishsound/fishsound_speex.c
Normal file
@ -0,0 +1,730 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "convert.h"
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#if HAVE_SPEEX
|
||||
|
||||
#if HAVE_SPEEX_1_1
|
||||
#include <speex/speex.h>
|
||||
#include <speex/speex_header.h>
|
||||
#include <speex/speex_stereo.h>
|
||||
#include <speex/speex_callbacks.h>
|
||||
|
||||
#else /* Speex 1.0 */
|
||||
|
||||
#include <speex.h>
|
||||
#include <speex_header.h>
|
||||
#include <speex_stereo.h>
|
||||
#include <speex_callbacks.h>
|
||||
#endif
|
||||
|
||||
/* Format for the vendor string: "Encoded with Speex VERSION", where VERSION
|
||||
* is the libspeex version as read from a newly-generated Speex header.
|
||||
*/
|
||||
#define VENDOR_FORMAT "Encoded with Speex %s"
|
||||
|
||||
#define DEFAULT_ENH_ENABLED 1
|
||||
|
||||
#define MAX_FRAME_BYTES 2000
|
||||
|
||||
typedef struct _FishSoundSpeexEnc {
|
||||
int frame_offset; /* number of speex frames done in this packet */
|
||||
int pcm_offset;
|
||||
char cbits[MAX_FRAME_BYTES];
|
||||
int id;
|
||||
} FishSoundSpeexEnc;
|
||||
|
||||
typedef struct _FishSoundSpeexInfo {
|
||||
int packetno;
|
||||
void * st;
|
||||
SpeexBits bits;
|
||||
int frame_size;
|
||||
int nframes;
|
||||
int extra_headers;
|
||||
SpeexStereoState stereo;
|
||||
int pcm_len; /* nr frames in pcm */
|
||||
float * ipcm; /* interleaved pcm */
|
||||
float * pcm[2]; /* Speex does max 2 channels */
|
||||
FishSoundSpeexEnc * enc;
|
||||
} FishSoundSpeexInfo;
|
||||
|
||||
int
|
||||
fish_sound_speex_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
SpeexHeader * header;
|
||||
|
||||
if (bytes < 8) return FISH_SOUND_UNKNOWN;
|
||||
|
||||
if (!strncmp ((char *)buf, "Speex ", 8)) {
|
||||
/* if only a short buffer was passed, do a weak identify */
|
||||
if (bytes == 8) return FISH_SOUND_SPEEX;
|
||||
|
||||
/* otherwise, assume the buffer is an entire initial header and
|
||||
* feed it to speex_packet_to_header() */
|
||||
if ((header = speex_packet_to_header ((char *)buf, (int)bytes)) != NULL) {
|
||||
fs_free(header);
|
||||
return FISH_SOUND_SPEEX;
|
||||
}
|
||||
}
|
||||
|
||||
return FISH_SOUND_UNKNOWN;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_speex_command (FishSound * fsound, int command, void * data, int datasize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if FS_DECODE
|
||||
static void *
|
||||
process_header(unsigned char * buf, long bytes, int enh_enabled,
|
||||
int * frame_size, int * rate,
|
||||
int * nframes, int forceMode, int * channels,
|
||||
SpeexStereoState * stereo, int * extra_headers)
|
||||
{
|
||||
void *st;
|
||||
SpeexMode *mode;
|
||||
SpeexHeader *header;
|
||||
int modeID;
|
||||
SpeexCallback callback;
|
||||
|
||||
header = speex_packet_to_header((char*)buf, (int)bytes);
|
||||
if (!header) {
|
||||
/*info_dialog_new ("Speex error", NULL, "Speex: cannot read header");*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (header->mode >= SPEEX_NB_MODES || header->mode < 0) {
|
||||
/*
|
||||
info_dialog_new ("Speex error", NULL,
|
||||
"Mode number %d does not (any longer) exist in this version\n",
|
||||
header->mode);
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
modeID = header->mode;
|
||||
if (forceMode!=-1)
|
||||
modeID = forceMode;
|
||||
/* speex_mode_list[] is declared const in speex 1.1.x, hence the cast */
|
||||
mode = (SpeexMode *)speex_mode_list[modeID];
|
||||
|
||||
if (header->speex_version_id > 1) {
|
||||
/*
|
||||
info_dialog_new ("Speex error", NULL,
|
||||
"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) {
|
||||
/*
|
||||
info_dialog_new ("Speex error", NULL,
|
||||
"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) {
|
||||
/*
|
||||
info_dialog_new ("Speex error", NULL,
|
||||
"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) {
|
||||
/*
|
||||
info_dialog_new ("Speex error", NULL,
|
||||
"Decoder initialization failed.\n");
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
|
||||
speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);
|
||||
|
||||
if (!(*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);
|
||||
}
|
||||
if (!*rate)
|
||||
*rate = header->rate;
|
||||
/* Adjust rate if --force-* options are used */
|
||||
if (forceMode!=-1)
|
||||
{
|
||||
if (header->mode < forceMode)
|
||||
*rate <<= (forceMode - header->mode);
|
||||
if (header->mode > forceMode)
|
||||
*rate >>= (header->mode - forceMode);
|
||||
}
|
||||
|
||||
speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, rate);
|
||||
|
||||
*nframes = header->frames_per_packet;
|
||||
|
||||
if (*channels == -1)
|
||||
*channels = header->nb_channels;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Decoding %d Hz audio using %s mode",
|
||||
*rate, mode->modeName);
|
||||
|
||||
if (*channels==1)
|
||||
fprintf (stderr, " (mono");
|
||||
else
|
||||
fprintf (stderr, " (stereo");
|
||||
|
||||
if (header->vbr)
|
||||
fprintf (stderr, " (VBR)\n");
|
||||
else
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
*extra_headers = header->extra_headers;
|
||||
|
||||
fs_free(header);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_speex_free_buffers (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
|
||||
if (fsound->mode == FISH_SOUND_DECODE) {
|
||||
if (fss->ipcm && fss->ipcm != fss->pcm[0]) fs_free (fss->ipcm);
|
||||
if (fss->pcm[0]) fs_free (fss->pcm[0]);
|
||||
if (fss->pcm[1]) fs_free (fss->pcm[1]);
|
||||
} else {
|
||||
if (fss->ipcm) fs_free (fss->ipcm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fs_speex_float_dispatch (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundDecoded_FloatIlv df;
|
||||
FishSoundDecoded_Float dfi;
|
||||
int retval;
|
||||
|
||||
if (fsound->interleave) {
|
||||
dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
|
||||
retval = dfi (fsound, (float **)fss->ipcm, fss->frame_size,
|
||||
fsound->user_data);
|
||||
} else {
|
||||
df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
|
||||
retval = df (fsound, fss->pcm, fss->frame_size, fsound->user_data);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_speex_decode (FishSound * fsound, unsigned char * buf, long bytes)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
int enh_enabled = DEFAULT_ENH_ENABLED;
|
||||
int rate = 0;
|
||||
int channels = -1;
|
||||
int forceMode = -1;
|
||||
int i, j;
|
||||
|
||||
if (fss->packetno == 0) {
|
||||
fss->st = process_header (buf, bytes, enh_enabled,
|
||||
&fss->frame_size, &rate,
|
||||
&fss->nframes, forceMode, &channels,
|
||||
&fss->stereo,
|
||||
&fss->extra_headers);
|
||||
|
||||
if (fss->st == NULL) {
|
||||
/* XXX: error */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("speex: got %d channels, %d Hz\n", channels, rate);
|
||||
#endif
|
||||
|
||||
fsound->info.samplerate = rate;
|
||||
fsound->info.channels = channels;
|
||||
|
||||
fss->ipcm = fs_malloc (sizeof (float) * fss->frame_size * channels);
|
||||
|
||||
if (channels == 1) {
|
||||
fss->pcm[0] = fss->ipcm;
|
||||
} else if (channels == 2) {
|
||||
fss->pcm[0] = fs_malloc (sizeof (float) * fss->frame_size);
|
||||
fss->pcm[1] = fs_malloc (sizeof (float) * fss->frame_size);
|
||||
}
|
||||
|
||||
if (fss->nframes == 0) fss->nframes = 1;
|
||||
|
||||
} else if (fss->packetno == 1) {
|
||||
/* Comments */
|
||||
fish_sound_comments_decode (fsound, buf, bytes);
|
||||
} else if (fss->packetno <= 1+fss->extra_headers) {
|
||||
/* Unknown extra headers */
|
||||
} else {
|
||||
speex_bits_read_from (&fss->bits, (char *)buf, (int)bytes);
|
||||
|
||||
for (i = 0; i < fss->nframes; i++) {
|
||||
/* Decode frame */
|
||||
speex_decode (fss->st, &fss->bits, fss->ipcm);
|
||||
|
||||
if (fsound->info.channels == 2) {
|
||||
speex_decode_stereo (fss->ipcm, fss->frame_size, &fss->stereo);
|
||||
if (fsound->interleave) {
|
||||
for (j = 0; j < fss->frame_size * fsound->info.channels; j++) {
|
||||
fss->ipcm[j] /= 32767.0;
|
||||
}
|
||||
} else {
|
||||
_fs_deinterleave ((float **)fss->ipcm, fss->pcm,
|
||||
fss->frame_size, 2, (float)(1/32767.0));
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < fss->frame_size; j++) {
|
||||
fss->ipcm[j] /= 32767.0;
|
||||
}
|
||||
}
|
||||
|
||||
fsound->frameno += fss->frame_size;
|
||||
|
||||
fs_speex_float_dispatch (fsound);
|
||||
}
|
||||
}
|
||||
|
||||
fss->packetno++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !FS_DECODE */
|
||||
|
||||
#define fs_speex_decode NULL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if FS_ENCODE
|
||||
static FishSound *
|
||||
fs_speex_enc_headers (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
SpeexMode * mode = NULL;
|
||||
SpeexHeader header;
|
||||
unsigned char * buf;
|
||||
int bytes;
|
||||
size_t buflen;
|
||||
|
||||
/* XXX: set wb, nb, uwb modes */
|
||||
/* These modes are declared const in speex 1.1.x, hence the explicit cast */
|
||||
mode = (SpeexMode *)&speex_wb_mode;
|
||||
|
||||
speex_init_header (&header, fsound->info.samplerate, 1, mode);
|
||||
header.frames_per_packet = fss->nframes; /* XXX: frames per packet */
|
||||
header.vbr = 1; /* XXX: VBR */
|
||||
header.nb_channels = fsound->info.channels;
|
||||
|
||||
fss->st = speex_encoder_init (mode);
|
||||
|
||||
if (fsound->callback.encoded) {
|
||||
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
|
||||
char vendor_string[128];
|
||||
|
||||
/* header */
|
||||
buf = (unsigned char *) speex_header_to_packet (&header, &bytes);
|
||||
encoded (fsound, buf, (long)bytes, fsound->user_data);
|
||||
fss->packetno++;
|
||||
fs_free (buf);
|
||||
|
||||
/* comments */
|
||||
snprintf (vendor_string, 128, VENDOR_FORMAT, header.speex_version);
|
||||
fish_sound_comment_set_vendor (fsound, vendor_string);
|
||||
bytes = fish_sound_comments_encode (fsound, NULL, 0);
|
||||
buf = fs_malloc (bytes);
|
||||
bytes = fish_sound_comments_encode (fsound, buf, bytes);
|
||||
encoded (fsound, buf, (long)bytes, fsound->user_data);
|
||||
fss->packetno++;
|
||||
fs_free (buf);
|
||||
}
|
||||
|
||||
speex_encoder_ctl (fss->st, SPEEX_SET_SAMPLING_RATE,
|
||||
&fsound->info.samplerate);
|
||||
|
||||
speex_encoder_ctl (fss->st, SPEEX_GET_FRAME_SIZE, &fss->frame_size);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("got frame size %d\n", fss->frame_size);
|
||||
#endif
|
||||
|
||||
/* XXX: blah blah blah ... set VBR etc. */
|
||||
|
||||
buflen = fss->frame_size * fsound->info.channels * sizeof (float);
|
||||
fss->ipcm = fs_malloc (buflen);
|
||||
memset (fss->ipcm, 0, buflen);
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_speex_encode_write (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
|
||||
int bytes;
|
||||
|
||||
speex_bits_insert_terminator (&fss->bits);
|
||||
bytes = speex_bits_write (&fss->bits, fse->cbits, MAX_FRAME_BYTES);
|
||||
speex_bits_reset (&fss->bits);
|
||||
|
||||
if (fsound->callback.encoded) {
|
||||
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
|
||||
|
||||
encoded (fsound, (unsigned char *)fse->cbits, (long)bytes,
|
||||
fsound->user_data);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_speex_encode_block (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
|
||||
long nencoded = fse->pcm_offset;
|
||||
|
||||
if (fsound->info.channels == 2)
|
||||
speex_encode_stereo (fss->ipcm, fse->pcm_offset, &fss->bits);
|
||||
|
||||
speex_encode (fss->st, fss->ipcm, &fss->bits);
|
||||
|
||||
fsound->frameno += fse->pcm_offset;
|
||||
fse->frame_offset++;
|
||||
|
||||
if (fse->frame_offset == fss->nframes) {
|
||||
fs_speex_encode_write (fsound);
|
||||
fse->frame_offset = 0;
|
||||
}
|
||||
|
||||
fse->pcm_offset = 0;
|
||||
|
||||
return nencoded;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_speex_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
|
||||
long remaining = frames, len, nencoded = 0;
|
||||
int j, start, end;
|
||||
int channels = fsound->info.channels;
|
||||
float * p = (float *)pcm;
|
||||
|
||||
if (fss->packetno == 0)
|
||||
fs_speex_enc_headers (fsound);
|
||||
|
||||
while (remaining > 0) {
|
||||
len = MIN (remaining, fss->frame_size - fse->pcm_offset);
|
||||
|
||||
start = fse->pcm_offset * channels;
|
||||
end = (len + fse->pcm_offset) * channels;
|
||||
for (j = start; j < end; j++) {
|
||||
fss->ipcm[j] = *p++ * (float)32767.0;
|
||||
}
|
||||
|
||||
fse->pcm_offset += len;
|
||||
|
||||
if (fse->pcm_offset == fss->frame_size) {
|
||||
nencoded += fs_speex_encode_block (fsound);
|
||||
}
|
||||
|
||||
remaining -= len;
|
||||
}
|
||||
|
||||
return frames - remaining;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_speex_encode_f (FishSound * fsound, float * pcm[], long frames)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
|
||||
long remaining = frames, len, n = 0, nencoded = 0;
|
||||
int j, start;
|
||||
|
||||
if (fss->packetno == 0)
|
||||
fs_speex_enc_headers (fsound);
|
||||
|
||||
while (remaining > 0) {
|
||||
len = MIN (remaining, fss->frame_size - fse->pcm_offset);
|
||||
|
||||
start = fse->pcm_offset;
|
||||
fss->pcm[0] = &pcm[0][n];
|
||||
|
||||
if (fsound->info.channels == 2) {
|
||||
fss->pcm[1] = &pcm[1][n];
|
||||
_fs_interleave (fss->pcm, (float **)&fss->ipcm[start*2],
|
||||
len, 2, 32767.0);
|
||||
} else {
|
||||
for (j = 0; j < len; j++) {
|
||||
fss->ipcm[start + j] = fss->pcm[0][j] * (float)32767.0;
|
||||
}
|
||||
}
|
||||
|
||||
fse->pcm_offset += len;
|
||||
|
||||
if (fse->pcm_offset == fss->frame_size) {
|
||||
nencoded += fs_speex_encode_block (fsound);
|
||||
}
|
||||
|
||||
remaining -= len;
|
||||
n += len;
|
||||
}
|
||||
|
||||
return frames - remaining;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_speex_flush (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
|
||||
long nencoded = 0;
|
||||
|
||||
if (fsound->mode != FISH_SOUND_ENCODE)
|
||||
return 0;
|
||||
|
||||
if (fse->pcm_offset > 0) {
|
||||
nencoded += fs_speex_encode_block (fsound);
|
||||
}
|
||||
|
||||
/* If, at this point, fse->frame_offset == 0, then either:
|
||||
- all remaining encoded data has just been flushed out via
|
||||
fs_speex_encode_block(), OR
|
||||
- there was no data remaining to flush at the beginning of this
|
||||
function (fse->pcm_offset == 0 && fse->frame_offset == 0)
|
||||
*/
|
||||
if (fse->frame_offset == 0) return 0;
|
||||
|
||||
while (fse->frame_offset < fss->nframes) {
|
||||
speex_bits_pack (&fss->bits, 15, 5);
|
||||
fse->frame_offset++;
|
||||
}
|
||||
|
||||
nencoded += fs_speex_encode_write (fsound);
|
||||
fse->frame_offset = 0;
|
||||
|
||||
return nencoded;
|
||||
}
|
||||
|
||||
#else /* !FS_ENCODE */
|
||||
|
||||
#define fs_speex_encode_f NULL
|
||||
#define fs_speex_encode_f_ilv NULL
|
||||
#define fs_speex_flush NULL
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
fs_speex_reset (FishSound * fsound)
|
||||
{
|
||||
/*FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_speex_update (FishSound * fsound, int interleave)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
size_t pcm_size = sizeof (float);
|
||||
|
||||
fss->ipcm = (float *)
|
||||
fs_realloc (fss->ipcm,
|
||||
pcm_size * fss->frame_size * fsound->info.channels);
|
||||
|
||||
if (interleave) {
|
||||
/* if transitioning from non-interleave to interleave,
|
||||
free non-ilv buffers */
|
||||
if (!fsound->interleave && fsound->info.channels == 2) {
|
||||
if (fss->pcm[0]) fs_free (fss->pcm[0]);
|
||||
if (fss->pcm[1]) fs_free (fss->pcm[1]);
|
||||
fss->pcm[0] = NULL;
|
||||
fss->pcm[1] = NULL;
|
||||
}
|
||||
} else {
|
||||
if (fsound->info.channels == 1) {
|
||||
fss->pcm[0] = (float *) fss->ipcm;
|
||||
} else if (fsound->info.channels == 2) {
|
||||
fss->pcm[0] = fs_realloc (fss->pcm[0], pcm_size * fss->frame_size);
|
||||
fss->pcm[1] = fs_realloc (fss->pcm[1], pcm_size * fss->frame_size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_speex_enc_init (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
FishSoundSpeexEnc * fse;
|
||||
|
||||
fse = fs_malloc (sizeof (FishSoundSpeexEnc));
|
||||
if (fse == NULL) return NULL;
|
||||
|
||||
fse->frame_offset = 0;
|
||||
fse->pcm_offset = 0;
|
||||
fse->id = 0;
|
||||
|
||||
fss->enc = fse;
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_speex_init (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss;
|
||||
SpeexStereoState stereo_init = SPEEX_STEREO_STATE_INIT;
|
||||
|
||||
fss = fs_malloc (sizeof (FishSoundSpeexInfo));
|
||||
if (fss == NULL) return NULL;
|
||||
|
||||
fss->packetno = 0;
|
||||
fss->st = NULL;
|
||||
fss->frame_size = 0;
|
||||
fss->nframes = 1;
|
||||
fss->pcm_len = 0;
|
||||
fss->ipcm = NULL;
|
||||
fss->pcm[0] = NULL;
|
||||
fss->pcm[1] = NULL;
|
||||
|
||||
memcpy (&fss->stereo, &stereo_init, sizeof (SpeexStereoState));
|
||||
|
||||
speex_bits_init (&fss->bits);
|
||||
|
||||
fsound->codec_data = fss;
|
||||
|
||||
if (fsound->mode == FISH_SOUND_ENCODE)
|
||||
fs_speex_enc_init (fsound);
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_speex_delete (FishSound * fsound)
|
||||
{
|
||||
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
|
||||
|
||||
fs_speex_free_buffers (fsound);
|
||||
|
||||
if (fsound->mode == FISH_SOUND_DECODE) {
|
||||
if (fss->st) speex_decoder_destroy (fss->st);
|
||||
} else if (fsound->mode == FISH_SOUND_ENCODE) {
|
||||
if (fss->st) speex_encoder_destroy (fss->st);
|
||||
if (fss->enc) fs_free (fss->enc);
|
||||
}
|
||||
speex_bits_destroy (&fss->bits);
|
||||
|
||||
fs_free (fss);
|
||||
fsound->codec_data = NULL;
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
FishSoundCodec *
|
||||
fish_sound_speex_codec (void)
|
||||
{
|
||||
FishSoundCodec * codec;
|
||||
|
||||
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
|
||||
|
||||
codec->format.format = FISH_SOUND_SPEEX;
|
||||
codec->format.name = "Speex (Xiph.Org)";
|
||||
codec->format.extension = "spx";
|
||||
|
||||
codec->init = fs_speex_init;
|
||||
codec->del = fs_speex_delete;
|
||||
codec->reset = fs_speex_reset;
|
||||
codec->update = fs_speex_update;
|
||||
codec->command = fs_speex_command;
|
||||
codec->decode = fs_speex_decode;
|
||||
codec->encode_f = fs_speex_encode_f;
|
||||
codec->encode_f_ilv = fs_speex_encode_f_ilv;
|
||||
codec->flush = fs_speex_flush;
|
||||
|
||||
return codec;
|
||||
}
|
||||
|
||||
#else /* !HAVE_SPEEX */
|
||||
|
||||
int
|
||||
fish_sound_speex_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
return FISH_SOUND_UNKNOWN;
|
||||
}
|
||||
|
||||
FishSoundCodec *
|
||||
fish_sound_speex_codec (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
508
modules/libfishsound/src/libfishsound/fishsound_vorbis.c
Normal file
508
modules/libfishsound/src/libfishsound/fishsound_vorbis.c
Normal file
@ -0,0 +1,508 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "convert.h"
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#if HAVE_VORBIS
|
||||
|
||||
#include <vorbis/codec.h>
|
||||
#if HAVE_VORBISENC
|
||||
#include <vorbis/vorbisenc.h>
|
||||
#endif
|
||||
|
||||
typedef struct _FishSoundVorbisInfo {
|
||||
int packetno;
|
||||
int finished;
|
||||
vorbis_info vi;
|
||||
vorbis_comment vc;
|
||||
vorbis_dsp_state vd; /** central working state for the PCM->packet encoder */
|
||||
vorbis_block vb; /** local working space for PCM->packet encode */
|
||||
float ** pcm; /** ongoing pcm working space for decoder (stateful) */
|
||||
float * ipcm; /** interleaved pcm for interfacing with user */
|
||||
long max_pcm;
|
||||
} FishSoundVorbisInfo;
|
||||
|
||||
int
|
||||
fish_sound_vorbis_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
struct vorbis_info vi;
|
||||
struct vorbis_comment vc;
|
||||
ogg_packet op;
|
||||
int ret, id = FISH_SOUND_UNKNOWN;
|
||||
|
||||
if (!strncmp ((char *)&buf[1], "vorbis", 6)) {
|
||||
/* if only a short buffer was passed, do a weak identify */
|
||||
if (bytes == 8) return FISH_SOUND_VORBIS;
|
||||
|
||||
/* otherwise, assume the buffer is an entire initial header and
|
||||
* feed it to vorbis_synthesis_headerin() */
|
||||
|
||||
vorbis_info_init (&vi);
|
||||
vorbis_comment_init (&vc);
|
||||
|
||||
op.packet = buf;
|
||||
op.bytes = bytes;
|
||||
op.b_o_s = 1;
|
||||
op.e_o_s = 0;
|
||||
op.granulepos = 0;
|
||||
op.packetno = 0;
|
||||
|
||||
if ((ret = vorbis_synthesis_headerin (&vi, &vc, &op)) == 0) {
|
||||
if (vi.rate != 0) id = FISH_SOUND_VORBIS;
|
||||
#ifdef DEBUG
|
||||
} else {
|
||||
printf ("vorbis_synthesis_headerin returned %d\n", ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
vorbis_info_clear (&vi);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_vorbis_command (FishSound * fsound, int command, void * data,
|
||||
int datasize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if FS_DECODE
|
||||
static long
|
||||
fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
ogg_packet op;
|
||||
long samples;
|
||||
int ret;
|
||||
|
||||
/* Make an ogg_packet structure to pass the data to libvorbis */
|
||||
op.packet = buf;
|
||||
op.bytes = bytes;
|
||||
op.b_o_s = (fsv->packetno == 0) ? 1 : 0;
|
||||
op.e_o_s = fsound->next_eos;
|
||||
op.granulepos = fsound->next_granulepos;
|
||||
op.packetno = fsv->packetno;
|
||||
|
||||
if (fsv->packetno < 3) {
|
||||
|
||||
if ((ret = vorbis_synthesis_headerin (&fsv->vi, &fsv->vc, &op)) == 0) {
|
||||
if (fsv->vi.rate != 0) {
|
||||
#ifdef DEBUG
|
||||
printf ("Got vorbis info: version %d\tchannels %d\trate %ld\n",
|
||||
fsv->vi.version, fsv->vi.channels, fsv->vi.rate);
|
||||
#endif
|
||||
fsound->info.samplerate = fsv->vi.rate;
|
||||
fsound->info.channels = fsv->vi.channels;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode comments from packet 1. Vorbis has 7 bytes of marker at the
|
||||
* start of vorbiscomment packet. */
|
||||
if (fsv->packetno == 1 && bytes > 7 && buf[0] == 0x03 &&
|
||||
!strncmp ((char *)&buf[1], "vorbis", 6)) {
|
||||
fish_sound_comments_decode (fsound, buf+7, bytes-7);
|
||||
} else if (fsv->packetno == 2) {
|
||||
vorbis_synthesis_init (&fsv->vd, &fsv->vi);
|
||||
vorbis_block_init (&fsv->vd, &fsv->vb);
|
||||
}
|
||||
} else {
|
||||
FishSoundDecoded_FloatIlv df;
|
||||
FishSoundDecoded_Float dfi;
|
||||
|
||||
if (vorbis_synthesis (&fsv->vb, &op) == 0)
|
||||
vorbis_synthesis_blockin (&fsv->vd, &fsv->vb);
|
||||
|
||||
while ((samples = vorbis_synthesis_pcmout (&fsv->vd, &fsv->pcm)) > 0) {
|
||||
vorbis_synthesis_read (&fsv->vd, samples);
|
||||
|
||||
if (fsound->frameno != -1)
|
||||
fsound->frameno += samples;
|
||||
|
||||
if (fsound->interleave) {
|
||||
if (samples > fsv->max_pcm) {
|
||||
fsv->ipcm = realloc (fsv->ipcm, sizeof(float) * samples *
|
||||
fsound->info.channels);
|
||||
fsv->max_pcm = samples;
|
||||
}
|
||||
_fs_interleave (fsv->pcm, (float **)fsv->ipcm, samples,
|
||||
fsound->info.channels, 1.0);
|
||||
|
||||
dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
|
||||
dfi (fsound, (float **)fsv->ipcm, samples, fsound->user_data);
|
||||
} else {
|
||||
df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
|
||||
df (fsound, fsv->pcm, samples, fsound->user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fsound->next_granulepos != -1) {
|
||||
fsound->frameno = fsound->next_granulepos;
|
||||
fsound->next_granulepos = -1;
|
||||
}
|
||||
|
||||
fsv->packetno++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !FS_DECODE */
|
||||
|
||||
#define fs_vorbis_decode NULL
|
||||
|
||||
#endif
|
||||
|
||||
#if FS_ENCODE && HAVE_VORBISENC
|
||||
|
||||
static FishSound *
|
||||
fs_vorbis_enc_headers (FishSound * fsound)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
const FishSoundComment * comment;
|
||||
ogg_packet header;
|
||||
ogg_packet header_comm;
|
||||
ogg_packet header_code;
|
||||
|
||||
/* Vorbis streams begin with three headers; the initial header (with
|
||||
most of the codec setup parameters) which is mandated by the Ogg
|
||||
bitstream spec. The second header holds any comment fields. The
|
||||
third header holds the bitstream codebook. We merely need to
|
||||
make the headers, then pass them to libvorbis one at a time;
|
||||
libvorbis handles the additional Ogg bitstream constraints */
|
||||
|
||||
/* Update the comments */
|
||||
for (comment = fish_sound_comment_first (fsound); comment;
|
||||
comment = fish_sound_comment_next (fsound, comment)) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "fs_vorbis_enc_headers: %s = %s\n",
|
||||
comment->name, comment->value);
|
||||
#endif
|
||||
vorbis_comment_add_tag (&fsv->vc, comment->name, comment->value);
|
||||
}
|
||||
|
||||
/* Generate the headers */
|
||||
vorbis_analysis_headerout(&fsv->vd, &fsv->vc,
|
||||
&header, &header_comm, &header_code);
|
||||
|
||||
/* Pass the generated headers to the user */
|
||||
if (fsound->callback.encoded) {
|
||||
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
|
||||
|
||||
encoded (fsound, header.packet, header.bytes, fsound->user_data);
|
||||
encoded (fsound, header_comm.packet, header_comm.bytes,
|
||||
fsound->user_data);
|
||||
encoded (fsound, header_code.packet, header_code.bytes,
|
||||
fsound->user_data);
|
||||
fsv->packetno = 3;
|
||||
}
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_vorbis_encode_write (FishSound * fsound, long len)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
ogg_packet op;
|
||||
|
||||
vorbis_analysis_wrote (&fsv->vd, len);
|
||||
|
||||
while (vorbis_analysis_blockout (&fsv->vd, &fsv->vb) == 1) {
|
||||
vorbis_analysis (&fsv->vb, NULL);
|
||||
vorbis_bitrate_addblock (&fsv->vb);
|
||||
|
||||
while (vorbis_bitrate_flushpacket (&fsv->vd, &op)) {
|
||||
if (fsound->callback.encoded) {
|
||||
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
|
||||
|
||||
if (op.granulepos != -1)
|
||||
fsound->frameno = op.granulepos;
|
||||
|
||||
encoded (fsound, op.packet, op.bytes, fsound->user_data);
|
||||
|
||||
fsv->packetno++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_vorbis_finish (FishSound * fsound)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
if (!fsv->finished) {
|
||||
if (fsound->mode == FISH_SOUND_ENCODE) {
|
||||
fs_vorbis_encode_write (fsound, 0);
|
||||
}
|
||||
fsv->finished = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_vorbis_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
float ** vpcm;
|
||||
long len, remaining = frames;
|
||||
float * d = (float *)pcm;
|
||||
|
||||
if (fsv->packetno == 0) {
|
||||
fs_vorbis_enc_headers (fsound);
|
||||
}
|
||||
|
||||
if (frames == 0) {
|
||||
fs_vorbis_finish (fsound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (remaining > 0) {
|
||||
len = MIN (1024, remaining);
|
||||
|
||||
/* expose the buffer to submit data */
|
||||
vpcm = vorbis_analysis_buffer (&fsv->vd, 1024);
|
||||
|
||||
_fs_deinterleave ((float **)d, vpcm, len, fsound->info.channels, 1.0);
|
||||
|
||||
d += (len * fsound->info.channels);
|
||||
|
||||
fs_vorbis_encode_write (fsound, len);
|
||||
|
||||
remaining -= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of input. Tell libvorbis we're at the end of stream so that it can
|
||||
* handle the last frame and mark the end of stream in the output properly.
|
||||
*/
|
||||
if (fsound->next_eos)
|
||||
fs_vorbis_finish (fsound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
fs_vorbis_encode_f (FishSound * fsound, float * pcm[], long frames)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
float ** vpcm;
|
||||
long len, remaining = frames;
|
||||
int i;
|
||||
float ** ppcm = alloca (sizeof (float *) * fsound->info.channels);
|
||||
|
||||
if (fsv->packetno == 0) {
|
||||
fs_vorbis_enc_headers (fsound);
|
||||
}
|
||||
|
||||
if (frames == 0) {
|
||||
fs_vorbis_finish (fsound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < fsound->info.channels; i++) {
|
||||
ppcm[i] = pcm[i];
|
||||
}
|
||||
|
||||
while (remaining > 0) {
|
||||
len = MIN (1024, remaining);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("fs_vorbis_encode: processing %ld frames\n", len);
|
||||
#endif
|
||||
|
||||
/* expose the buffer to submit data */
|
||||
vpcm = vorbis_analysis_buffer (&fsv->vd, 1024);
|
||||
|
||||
for (i = 0; i < fsound->info.channels; i++) {
|
||||
memcpy (vpcm[i], ppcm[i], sizeof (float) * len);
|
||||
}
|
||||
|
||||
fs_vorbis_encode_write (fsound, len);
|
||||
|
||||
remaining -= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of input. Tell libvorbis we're at the end of stream so that it can
|
||||
* handle the last frame and mark the end of stream in the output properly.
|
||||
*/
|
||||
if (fsound->next_eos)
|
||||
fs_vorbis_finish (fsound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_vorbis_enc_init (FishSound * fsound)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("Vorbis enc init: %d channels, %d Hz\n", fsound->info.channels,
|
||||
fsound->info.samplerate);
|
||||
#endif
|
||||
|
||||
|
||||
vorbis_encode_init_vbr (&fsv->vi, fsound->info.channels,
|
||||
fsound->info.samplerate, (float)0.3 /* quality */);
|
||||
|
||||
/* set up the analysis state and auxiliary encoding storage */
|
||||
vorbis_analysis_init (&fsv->vd, &fsv->vi);
|
||||
vorbis_block_init (&fsv->vd, &fsv->vb);
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
#else /* ! FS_ENCODE && HAVE_VORBISENC */
|
||||
|
||||
#define fs_vorbis_encode_f NULL
|
||||
#define fs_vorbis_encode_f_ilv NULL
|
||||
#define fs_vorbis_finish NULL
|
||||
|
||||
#endif /* ! FS_ENCODE && HAVE_VORBISENC */
|
||||
|
||||
static int
|
||||
fs_vorbis_reset (FishSound * fsound)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
vorbis_block_init (&fsv->vd, &fsv->vb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_vorbis_init (FishSound * fsound)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv;
|
||||
|
||||
fsv = fs_malloc (sizeof (FishSoundVorbisInfo));
|
||||
if (fsv == NULL) return NULL;
|
||||
|
||||
fsv->packetno = 0;
|
||||
fsv->finished = 0;
|
||||
vorbis_info_init (&fsv->vi);
|
||||
vorbis_comment_init (&fsv->vc);
|
||||
fsv->pcm = NULL;
|
||||
fsv->ipcm = NULL;
|
||||
fsv->max_pcm = 0;
|
||||
|
||||
fsound->codec_data = fsv;
|
||||
|
||||
#if FS_ENCODE && HAVE_VORBISENC
|
||||
|
||||
if (fsound->mode == FISH_SOUND_ENCODE) {
|
||||
fs_vorbis_enc_init (fsound);
|
||||
}
|
||||
|
||||
#endif /* FS_ENCODE && HAVE_VORBISENC */
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
static FishSound *
|
||||
fs_vorbis_delete (FishSound * fsound)
|
||||
{
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
#if FS_ENCODE && HAVE_VORBISENC
|
||||
fs_vorbis_finish (fsound);
|
||||
#endif /* FS_ENCODE && HAVE_VORBISENC */
|
||||
|
||||
if (fsv->ipcm) fs_free (fsv->ipcm);
|
||||
|
||||
vorbis_block_clear (&fsv->vb);
|
||||
vorbis_dsp_clear (&fsv->vd);
|
||||
vorbis_comment_clear (&fsv->vc);
|
||||
vorbis_info_clear (&fsv->vi);
|
||||
|
||||
fs_free (fsv);
|
||||
fsound->codec_data = NULL;
|
||||
|
||||
return fsound;
|
||||
}
|
||||
|
||||
FishSoundCodec *
|
||||
fish_sound_vorbis_codec (void)
|
||||
{
|
||||
FishSoundCodec * codec;
|
||||
|
||||
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
|
||||
|
||||
codec->format.format = FISH_SOUND_VORBIS;
|
||||
codec->format.name = "Vorbis (Xiph.Org)";
|
||||
codec->format.extension = "ogg";
|
||||
|
||||
codec->init = fs_vorbis_init;
|
||||
codec->del = fs_vorbis_delete;
|
||||
codec->reset = fs_vorbis_reset;
|
||||
codec->update = NULL; /* XXX */
|
||||
codec->command = fs_vorbis_command;
|
||||
codec->decode = fs_vorbis_decode;
|
||||
codec->encode_f = fs_vorbis_encode_f;
|
||||
codec->encode_f_ilv = fs_vorbis_encode_f_ilv;
|
||||
codec->flush = NULL;
|
||||
|
||||
return codec;
|
||||
}
|
||||
|
||||
#else /* !HAVE_VORBIS */
|
||||
|
||||
int
|
||||
fish_sound_vorbis_identify (unsigned char * buf, long bytes)
|
||||
{
|
||||
return FISH_SOUND_UNKNOWN;
|
||||
}
|
||||
|
||||
FishSoundCodec *
|
||||
fish_sound_vorbis_codec (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
57
modules/libfishsound/src/libfishsound/fs_compat.h
Normal file
57
modules/libfishsound/src/libfishsound/fs_compat.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 "config.h"
|
||||
|
||||
/* WINDOWS */
|
||||
#ifdef _WIN32
|
||||
#define inline __inline
|
||||
#define alloca _alloca
|
||||
#define strncasecmp _strnicmp
|
||||
#define snprintf _snprintf
|
||||
#ifndef __SYMBIAN32__
|
||||
#define strcasecmp _stricmp
|
||||
#endif /* ! __SYMBIAN32__ */
|
||||
#endif
|
||||
|
||||
/* malloc/realloc/free macros */
|
||||
#ifndef fs_malloc
|
||||
#define fs_malloc malloc
|
||||
#endif
|
||||
|
||||
#ifndef fs_realloc
|
||||
#define fs_realloc realloc
|
||||
#endif
|
||||
|
||||
#ifndef fs_free
|
||||
#define fs_free free
|
||||
#endif
|
234
modules/libfishsound/src/libfishsound/fs_vector.c
Normal file
234
modules/libfishsound/src/libfishsound/fs_vector.c
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fs_compat.h"
|
||||
|
||||
typedef int (*FishSoundFunc) (void * data);
|
||||
typedef int (*FishSoundCmpFunc) (const void * data1, const void * data2);
|
||||
|
||||
typedef struct _FishSoundVector FishSoundVector;
|
||||
|
||||
struct _FishSoundVector {
|
||||
int max_elements;
|
||||
int nr_elements;
|
||||
FishSoundCmpFunc cmp;
|
||||
void ** data;
|
||||
};
|
||||
|
||||
/*
|
||||
* A vector of void *. New elements will be appended at the tail.
|
||||
*/
|
||||
|
||||
FishSoundVector *
|
||||
fs_vector_new (FishSoundCmpFunc cmp)
|
||||
{
|
||||
FishSoundVector * vector;
|
||||
|
||||
vector = fs_malloc (sizeof (FishSoundVector));
|
||||
|
||||
vector->max_elements = 0;
|
||||
vector->nr_elements = 0;
|
||||
vector->cmp = cmp;
|
||||
vector->data = NULL;
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_vector_clear (FishSoundVector * vector)
|
||||
{
|
||||
fs_free (vector->data);
|
||||
vector->data = NULL;
|
||||
vector->nr_elements = 0;
|
||||
vector->max_elements = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fs_vector_delete (FishSoundVector * vector)
|
||||
{
|
||||
fs_vector_clear (vector);
|
||||
fs_free (vector);
|
||||
}
|
||||
|
||||
int
|
||||
fs_vector_size (FishSoundVector * vector)
|
||||
{
|
||||
if (vector == NULL) return 0;
|
||||
|
||||
return vector->nr_elements;
|
||||
}
|
||||
|
||||
void *
|
||||
fs_vector_nth (FishSoundVector * vector, int n)
|
||||
{
|
||||
if (vector == NULL) return NULL;
|
||||
|
||||
if (n >= vector->nr_elements) return NULL;
|
||||
|
||||
return vector->data[n];
|
||||
}
|
||||
|
||||
int
|
||||
fs_vector_find_index (FishSoundVector * vector, const void * data)
|
||||
{
|
||||
void * v_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vector->nr_elements; i++) {
|
||||
v_data = vector->data[i];
|
||||
if (vector->cmp (v_data, data))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *
|
||||
fs_vector_find (FishSoundVector * vector, const void * data)
|
||||
{
|
||||
void * v_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vector->nr_elements; i++) {
|
||||
v_data = vector->data[i];
|
||||
if (vector->cmp (v_data, data))
|
||||
return v_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
fs_vector_foreach (FishSoundVector * vector, FishSoundFunc func)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vector->nr_elements; i++) {
|
||||
func (vector->data[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FishSoundVector *
|
||||
fs_vector_grow (FishSoundVector * vector)
|
||||
{
|
||||
void * new_elements;
|
||||
int new_max_elements;
|
||||
|
||||
vector->nr_elements++;
|
||||
|
||||
if (vector->nr_elements > vector->max_elements) {
|
||||
if (vector->max_elements == 0) {
|
||||
new_max_elements = 1;
|
||||
} else {
|
||||
new_max_elements = vector->max_elements * 2;
|
||||
}
|
||||
|
||||
new_elements =
|
||||
fs_realloc (vector->data, (size_t)new_max_elements * sizeof (void *));
|
||||
|
||||
if (new_elements == NULL) {
|
||||
vector->nr_elements--;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vector->max_elements = new_max_elements;
|
||||
vector->data = new_elements;
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
void *
|
||||
fs_vector_insert (FishSoundVector * vector, void * data)
|
||||
{
|
||||
if (fs_vector_grow (vector) == NULL)
|
||||
return NULL;
|
||||
|
||||
vector->data[vector->nr_elements-1] = data;
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
static void *
|
||||
fs_vector_remove_nth (FishSoundVector * vector, int n)
|
||||
{
|
||||
int i;
|
||||
void * new_elements;
|
||||
int new_max_elements;
|
||||
|
||||
vector->nr_elements--;
|
||||
|
||||
if (vector->nr_elements == 0) {
|
||||
fs_vector_clear (vector);
|
||||
} else {
|
||||
for (i = n; i < vector->nr_elements; i++) {
|
||||
vector->data[i] = vector->data[i+1];
|
||||
}
|
||||
|
||||
if (vector->nr_elements < vector->max_elements/2) {
|
||||
new_max_elements = vector->max_elements/2;
|
||||
|
||||
new_elements =
|
||||
fs_realloc (vector->data,
|
||||
(size_t)new_max_elements * sizeof (void *));
|
||||
|
||||
if (new_elements == NULL)
|
||||
return NULL;
|
||||
|
||||
vector->max_elements = new_max_elements;
|
||||
vector->data = new_elements;
|
||||
}
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
FishSoundVector *
|
||||
fs_vector_remove (FishSoundVector * vector, void * data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vector->nr_elements; i++) {
|
||||
if (vector->data[i] == data) {
|
||||
return fs_vector_remove_nth (vector, i);
|
||||
}
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
80
modules/libfishsound/src/libfishsound/fs_vector.h
Normal file
80
modules/libfishsound/src/libfishsound/fs_vector.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FS_VECTOR_H__
|
||||
#define __FS_VECTOR_H__
|
||||
|
||||
typedef void FishSoundVector;
|
||||
|
||||
typedef int (*FishSoundFunc) (void * data);
|
||||
typedef int (*FishSoundCmpFunc) (void * data1, void * data2);
|
||||
|
||||
FishSoundVector *
|
||||
fs_vector_new (FishSoundCmpFunc cmp);
|
||||
|
||||
void
|
||||
fs_vector_delete (FishSoundVector * vector);
|
||||
|
||||
void *
|
||||
fs_vector_nth (FishSoundVector * vector, int n);
|
||||
|
||||
int
|
||||
fs_vector_find_index (FishSoundVector * vector, const void * data);
|
||||
|
||||
void *
|
||||
fs_vector_find (FishSoundVector * vector, const void * data);
|
||||
|
||||
int
|
||||
fs_vector_foreach (FishSoundVector * vector, FishSoundFunc func);
|
||||
|
||||
int
|
||||
fs_vector_size (FishSoundVector * vector);
|
||||
|
||||
/**
|
||||
* Add an element to a vector.
|
||||
* \param vector An FishSoundVector
|
||||
* \param data The new element to add
|
||||
* \retval data If the element was successfully added
|
||||
* \retval NULL If adding the element failed due to a realloc() error
|
||||
*/
|
||||
void *
|
||||
fs_vector_insert (FishSoundVector * vector, void * data);
|
||||
|
||||
/**
|
||||
* Remove a (void *) element of a vector
|
||||
* \retval \a vector on success
|
||||
* \retval NULL on failure (realloc error)
|
||||
*/
|
||||
FishSoundVector *
|
||||
fs_vector_remove (FishSoundVector * vector, void * data);
|
||||
|
||||
#endif /* __FS_VECTOR_H__ */
|
189
modules/libfishsound/src/libfishsound/private.h
Normal file
189
modules/libfishsound/src/libfishsound/private.h
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 CSIRO Australia 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 ORGANISATION 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.
|
||||
*/
|
||||
|
||||
#ifndef __FISH_SOUND_PRIVATE_H__
|
||||
#define __FISH_SOUND_PRIVATE_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fs_compat.h"
|
||||
#include "fs_vector.h"
|
||||
|
||||
#include <fishsound/constants.h>
|
||||
|
||||
#undef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
typedef struct _FishSound FishSound;
|
||||
typedef struct _FishSoundInfo FishSoundInfo;
|
||||
typedef struct _FishSoundCodec FishSoundCodec;
|
||||
typedef struct _FishSoundFormat FishSoundFormat;
|
||||
typedef struct _FishSoundComment FishSoundComment;
|
||||
|
||||
typedef int (*FSCodecIdentify) (unsigned char * buf, long bytes);
|
||||
typedef FishSound * (*FSCodecInit) (FishSound * fsound);
|
||||
typedef FishSound * (*FSCodecDelete) (FishSound * fsound);
|
||||
typedef int (*FSCodecReset) (FishSound * fsound);
|
||||
typedef int (*FSCodecUpdate) (FishSound * fsound, int interleave);
|
||||
typedef int (*FSCodecCommand) (FishSound * fsound, int command,
|
||||
void * data, int datasize);
|
||||
typedef long (*FSCodecDecode) (FishSound * fsound, unsigned char * buf,
|
||||
long bytes);
|
||||
typedef long (*FSCodecEncode_Float) (FishSound * fsound, float * pcm[],
|
||||
long frames);
|
||||
typedef long (*FSCodecEncode_FloatIlv) (FishSound * fsound,
|
||||
float ** pcm, long frames);
|
||||
typedef long (*FSCodecFlush) (FishSound * fsound);
|
||||
|
||||
#include <fishsound/decode.h>
|
||||
#include <fishsound/encode.h>
|
||||
|
||||
struct _FishSoundFormat {
|
||||
int format;
|
||||
const char * name;
|
||||
const char * extension;
|
||||
};
|
||||
|
||||
struct _FishSoundCodec {
|
||||
struct _FishSoundFormat format;
|
||||
FSCodecInit init;
|
||||
FSCodecDelete del;
|
||||
FSCodecReset reset;
|
||||
FSCodecUpdate update;
|
||||
FSCodecCommand command;
|
||||
FSCodecDecode decode;
|
||||
FSCodecEncode_FloatIlv encode_f_ilv;
|
||||
FSCodecEncode_Float encode_f;
|
||||
FSCodecFlush flush;
|
||||
};
|
||||
|
||||
struct _FishSoundInfo {
|
||||
int samplerate;
|
||||
int channels;
|
||||
int format;
|
||||
};
|
||||
|
||||
struct _FishSoundComment {
|
||||
char * name;
|
||||
char * value;
|
||||
};
|
||||
|
||||
union FishSoundCallback {
|
||||
FishSoundDecoded_Float decoded_float;
|
||||
FishSoundDecoded_FloatIlv decoded_float_ilv;
|
||||
FishSoundEncoded encoded;
|
||||
};
|
||||
|
||||
struct _FishSound {
|
||||
/** FISH_SOUND_DECODE or FISH_SOUND_ENCODE */
|
||||
FishSoundMode mode;
|
||||
|
||||
/** General info related to sound */
|
||||
FishSoundInfo info;
|
||||
|
||||
/** Interleave boolean */
|
||||
int interleave;
|
||||
|
||||
/**
|
||||
* Current frameno.
|
||||
*/
|
||||
long frameno;
|
||||
|
||||
/**
|
||||
* Truncation frameno for the next block of data sent to decode.
|
||||
* In Ogg encapsulation, this is represented by the Ogg packet's
|
||||
* "granulepos" field.
|
||||
*/
|
||||
long next_granulepos;
|
||||
|
||||
/**
|
||||
* Flag if the next block of data sent to decode will be the last one
|
||||
* for this stream (eos = End Of Stream).
|
||||
* In Ogg encapsulation, this is represented by the Ogg packet's
|
||||
* "eos" field.
|
||||
*/
|
||||
int next_eos;
|
||||
|
||||
/** The codec class structure */
|
||||
FishSoundCodec * codec;
|
||||
|
||||
/** codec specific data */
|
||||
void * codec_data;
|
||||
|
||||
/* encode or decode callback */
|
||||
union FishSoundCallback callback;
|
||||
|
||||
/** user data for encode/decode callback */
|
||||
void * user_data;
|
||||
|
||||
/** The comments */
|
||||
char * vendor;
|
||||
FishSoundVector * comments;
|
||||
};
|
||||
|
||||
int fish_sound_identify (unsigned char * buf, long bytes);
|
||||
int fish_sound_set_format (FishSound * fsound, int format);
|
||||
|
||||
/* Format specific interfaces */
|
||||
int fish_sound_vorbis_identify (unsigned char * buf, long bytes);
|
||||
FishSoundCodec * fish_sound_vorbis_codec (void);
|
||||
|
||||
int fish_sound_speex_identify (unsigned char * buf, long bytes);
|
||||
FishSoundCodec * fish_sound_speex_codec (void);
|
||||
|
||||
int fish_sound_flac_identify (unsigned char * buf, long bytes);
|
||||
FishSoundCodec * fish_sound_flac_codec (void);
|
||||
|
||||
/* comments */
|
||||
int fish_sound_comments_init (FishSound * fsound);
|
||||
int fish_sound_comments_free (FishSound * fsound);
|
||||
int fish_sound_comments_decode (FishSound * fsound, unsigned char * buf,
|
||||
long bytes);
|
||||
long fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
|
||||
long length);
|
||||
|
||||
/**
|
||||
* Set the vendor string.
|
||||
* \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
|
||||
* \param vendor The vendor string.
|
||||
* \retval 0 Success
|
||||
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
|
||||
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
|
||||
*/
|
||||
int
|
||||
fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor);
|
||||
|
||||
const FishSoundComment * fish_sound_comment_first (FishSound * fsound);
|
||||
const FishSoundComment *
|
||||
fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment);
|
||||
|
||||
#endif /* __FISH_SOUND_PRIVATE_H__ */
|
40
modules/libfishsound/update.sh
Normal file
40
modules/libfishsound/update.sh
Normal file
@ -0,0 +1,40 @@
|
||||
# Usage: cp $1/update.sh <libfishsound_src_directory>
|
||||
#
|
||||
# Copies the needed files from a directory containing the original
|
||||
# libfishsound source that we need for the Mozilla HTML5 media support.
|
||||
cp $1/config.h ./include/fishsound/config.h
|
||||
echo "#undef FS_ENCODE" >>./include/fishsound/config.h
|
||||
echo "#define FS_ENCODE 0" >>./include/fishsound/config.h
|
||||
echo "#undef HAVE_FLAC" >>./include/fishsound/config.h
|
||||
echo "#define HAVE_FLAC 0" >>./include/fishsound/config.h
|
||||
echo "#undef HAVE_OGGZ" >>./include/fishsound/config.h
|
||||
echo "#define HAVE_OGGZ 1" >>./include/fishsound/config.h
|
||||
echo "#undef HAVE_SPEEX" >>./include/fishsound/config.h
|
||||
echo "#define HAVE_SPEEX 0" >>./include/fishsound/config.h
|
||||
echo "#undef HAVE_VORBIS" >>./include/fishsound/config.h
|
||||
echo "#define HAVE_VORBIS 1" >>./include/fishsound/config.h
|
||||
echo "#undef HAVE_VORBISENC" >>./include/fishsound/config.h
|
||||
echo "#define HAVE_VORBISENC 0" >>./include/fishsound/config.h
|
||||
echo "#undef DEBUG" >>./include/fishsound/config.h
|
||||
cp $1/include/fishsound/encode.h ./include/fishsound/encode.h
|
||||
cp $1/include/fishsound/comments.h ./include/fishsound/comments.h
|
||||
cp $1/include/fishsound/deprecated.h ./include/fishsound/deprecated.h
|
||||
cp $1/include/fishsound/fishsound.h ./include/fishsound/fishsound.h
|
||||
cp $1/include/fishsound/constants.h ./include/fishsound/constants.h
|
||||
cp $1/include/fishsound/decode.h ./include/fishsound/decode.h
|
||||
cp $1/COPYING ./COPYING
|
||||
cp $1/README ./README
|
||||
cp ./include/fishsound/config.h ./src/libfishsound/config.h
|
||||
cp $1/src/libfishsound/decode.c ./src/libfishsound/fishsound_decode.c
|
||||
cp $1/src/libfishsound/fishsound.c ./src/libfishsound/fishsound.c
|
||||
sed s/\#include\ \<vorbis\\/vorbisenc.h\>/\#if\ HAVE_VORBISENC\\n\#include\ \<vorbis\\/vorbisenc.h\>\\n\#endif/g $1/src/libfishsound/vorbis.c >./src/libfishsound/fishsound_vorbis.c
|
||||
cp $1/src/libfishsound/flac.c ./src/libfishsound/fishsound_flac.c
|
||||
cp $1/src/libfishsound/comments.c ./src/libfishsound/fishsound_comments.c
|
||||
cp $1/src/libfishsound/private.h ./src/libfishsound/private.h
|
||||
cp $1/src/libfishsound/fs_compat.h ./src/libfishsound/fs_compat.h
|
||||
cp $1/src/libfishsound/speex.c ./src/libfishsound/fishsound_speex.c
|
||||
cp $1/src/libfishsound/encode.c ./src/libfishsound/fishsound_encode.c
|
||||
cp $1/src/libfishsound/fs_vector.h ./src/libfishsound/fs_vector.h
|
||||
cp $1/src/libfishsound/fs_vector.c ./src/libfishsound/fs_vector.c
|
||||
cp $1/src/libfishsound/convert.h ./src/libfishsound/convert.h
|
||||
cp $1/AUTHORS ./AUTHORS
|
Loading…
x
Reference in New Issue
Block a user