Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F125944
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
144 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/music-player.cpp b/util/music-player.cpp
index 59d354ba..4e9c0a45 100644
--- a/util/music-player.cpp
+++ b/util/music-player.cpp
@@ -1,888 +1,901 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
#endif
#include "music-player.h"
#include "globals.h"
#include "util/debug.h"
#include <iostream>
#include "configuration.h"
#include "sound.h"
#include "dumb/include/dumb.h"
#include "gme/Music_Emu.h"
#include "exceptions/exception.h"
#include <sstream>
#include <stdio.h>
#ifdef USE_ALLEGRO5
#include <allegro5/allegro_audio.h>
#endif
#ifdef USE_ALLEGRO
#include "dumb/include/aldumb.h"
#ifdef _WIN32
/* what do we need winalleg for?
* reason: ...
*/
#include <winalleg.h>
#endif
#endif
#ifdef HAVE_MP3_MPG123
#include <mpg123.h>
#endif
#ifdef HAVE_MP3_MAD
#include <mad.h>
#endif
#ifdef USE_SDL
#include "sdl/mixer/SDL_mixer.h"
#endif
using std::string;
namespace Util{
class MusicException: public Exception::Base {
public:
MusicException(const std::string & file, int line, const std::string & reason):
Exception::Base(file, line),
reason(reason){
}
MusicException(const MusicException & copy):
Exception::Base(copy),
reason(copy.reason){
}
virtual ~MusicException() throw(){
}
protected:
virtual const std::string getReason() const {
return reason;
}
virtual Exception::Base * copy() const {
return new MusicException(*this);
}
std::string reason;
};
static double scaleVolume(double start){
return start;
}
/* 1 for big endian (most significant byte)
* 0 for little endian (least significant byte)
*/
/* FIXME: move this to global or something and find a better #ifdef */
int bigEndian(){
#if defined(PS3) || defined(WII)
return 1;
#else
return 0;
#endif
}
#ifdef USE_ALLEGRO5
const int DUMB_SAMPLES = 1024;
MusicRenderer::MusicRenderer(){
create(Sound::Info.frequency, 2);
}
MusicRenderer::MusicRenderer(int frequency, int channels){
create(frequency, channels);
}
void MusicRenderer::create(int frequency, int channels){
ALLEGRO_CHANNEL_CONF configuration = ALLEGRO_CHANNEL_CONF_2;
switch (channels){
case 1: configuration = ALLEGRO_CHANNEL_CONF_1; break;
case 2: configuration = ALLEGRO_CHANNEL_CONF_2; break;
case 3: configuration = ALLEGRO_CHANNEL_CONF_3; break;
case 4: configuration = ALLEGRO_CHANNEL_CONF_4; break;
case 5: configuration = ALLEGRO_CHANNEL_CONF_5_1; break;
case 6: configuration = ALLEGRO_CHANNEL_CONF_6_1; break;
case 7: configuration = ALLEGRO_CHANNEL_CONF_7_1; break;
default: configuration = ALLEGRO_CHANNEL_CONF_2; break;
}
stream = al_create_audio_stream(4, DUMB_SAMPLES, frequency, ALLEGRO_AUDIO_DEPTH_INT16, configuration);
if (!stream){
throw MusicException(__FILE__, __LINE__, "Could not create allegro5 audio stream");
}
queue = al_create_event_queue();
al_register_event_source(queue, al_get_audio_stream_event_source(stream));
}
void MusicRenderer::play(MusicPlayer & player){
al_attach_audio_stream_to_mixer(stream, al_get_default_mixer());
}
void MusicRenderer::pause(){
al_detach_audio_stream(stream);
}
MusicRenderer::~MusicRenderer(){
al_destroy_audio_stream(stream);
al_destroy_event_queue(queue);
}
void MusicRenderer::poll(MusicPlayer & player){
ALLEGRO_EVENT event;
while (al_get_next_event(queue, &event)){
if (event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT) {
ALLEGRO_AUDIO_STREAM * stream = (ALLEGRO_AUDIO_STREAM *) event.any.source;
void * data = al_get_audio_stream_fragment(stream);
if (data != NULL){
player.render(data, al_get_audio_stream_length(stream));
al_set_audio_stream_fragment(stream, data);
}
}
}
}
#elif USE_SDL
static const int BUFFER_SIZE = 4096;
-MusicRenderer::MusicRenderer(){
+int formatType(){
+ if (bigEndian()){
+ return AUDIO_S16MSB;
+ } else {
+ return AUDIO_S16;
+ }
+}
+MusicRenderer::MusicRenderer():
+convert(formatType(), Sound::Info.channels, Sound::Info.frequency,
+ formatType(), Sound::Info.channels, Sound::Info.frequency){
create(Sound::Info.frequency, Sound::Info.channels);
}
-MusicRenderer::MusicRenderer(int frequency, int channels){
+MusicRenderer::MusicRenderer(int frequency, int channels):
+convert(formatType(), channels, frequency,
+ formatType(), Sound::Info.channels, Sound::Info.frequency){
create(frequency, channels);
}
void MusicRenderer::create(int frequency, int channels){
- int format = AUDIO_S16;
- if (bigEndian()){
- format = AUDIO_S16MSB;
- }
- Global::debug(1) << "Convert between " << format << ", " << channels << ", " << frequency << " to " << Sound::Info.format << ", " << Sound::Info.channels << ", " << Sound::Info.frequency << std::endl;
+
+ // Global::debug(1) << "Convert between " << format << ", " << channels << ", " << frequency << " to " << Sound::Info.format << ", " << Sound::Info.channels << ", " << Sound::Info.frequency << std::endl;
+ /*
SDL_BuildAudioCVT(&convert, format, channels, frequency,
Sound::Info.format, Sound::Info.channels,
Sound::Info.frequency);
- data = new Uint8[BUFFER_SIZE * convert.len_mult];
+ */
+ data = new Uint8[convert.convertedLength(BUFFER_SIZE)];
position = 0;
converted = 0;
}
void MusicRenderer::fill(MusicPlayer * player){
position = 0;
/* read samples in dual-channel, 16-bit, signed form */
player->render(data, BUFFER_SIZE / 4);
+ converted = convert.convert(data, BUFFER_SIZE);
+#if 0
if (convert.needed){
convert.buf = data;
convert.len = BUFFER_SIZE;
/* then convert to whatever the real output wants */
SDL_ConvertAudio(&convert);
converted = convert.len_cvt;
} else {
converted = BUFFER_SIZE;
}
+#endif
}
void MusicRenderer::read(MusicPlayer * player, Uint8 * stream, int bytes){
while (bytes > 0){
int length = bytes;
if (length + position >= converted){
length = converted - position;
}
/* data contains samples in the same format as the output */
memcpy(stream, data + position, length);
stream += length;
position += length;
bytes -= length;
if (position >= converted){
fill(player);
}
}
}
void MusicRenderer::mixer(void * arg, Uint8 * stream, int bytes){
MusicPlayer * player = (MusicPlayer*) arg;
player->getRenderer()->read(player, stream, bytes);
/*
int size = (int)((float) bytes / player->getRenderer()->convert.len_ratio / (float) player->getRenderer()->convert.len_mult);
Global::debug(2) << "Incoming " << bytes << " render " << size << std::endl;
player->getRenderer()->convert.buf = player->getRenderer()->data;
player->getRenderer()->convert.len = size;
// player->render(stream, bytes / 4);
player->render(player->getRenderer()->data, size / 4);
SDL_ConvertAudio(&player->getRenderer()->convert);
memcpy(stream, player->getRenderer()->data, bytes);
*/
}
void MusicRenderer::play(MusicPlayer & player){
Mix_HookMusic(mixer, &player);
}
void MusicRenderer::pause(){
Mix_HookMusic(NULL, NULL);
}
void MusicRenderer::poll(MusicPlayer & player){
}
MusicRenderer::~MusicRenderer(){
Mix_HookMusic(NULL, NULL);
delete[] data;
}
#elif USE_ALLEGRO
int BUFFER_SIZE = 1 << 11;
static int ALLEGRO_MONO = 0;
static int ALLEGRO_STEREO = 1;
MusicRenderer::MusicRenderer(){
create(Sound::Info.frequency, 2);
}
MusicRenderer::MusicRenderer(int frequency, int channels){
create(frequency, channels);
}
void MusicRenderer::create(int frequency, int channels){
int configuration = ALLEGRO_STEREO;
if (channels == 1){
configuration = ALLEGRO_MONO;
}
stream = play_audio_stream(BUFFER_SIZE, 16, configuration, frequency, 255, 128);
if (!stream){
throw MusicException(__FILE__, __LINE__, "Could not create Allegro stream");
}
if (stream->len != BUFFER_SIZE){
throw MusicException(__FILE__, __LINE__, "Buffer size mismatch");
}
voice_set_priority(stream->voice, 255);
}
void MusicRenderer::play(MusicPlayer & player){
voice_start(stream->voice);
}
void MusicRenderer::pause(){
voice_stop(stream->voice);
}
void MusicRenderer::poll(MusicPlayer & player){
short * buffer = (short*) get_audio_stream_buffer(stream);
if (buffer){
player.render(buffer, BUFFER_SIZE);
/* allegro wants unsigned data but gme produces signed so to convert
* signed samples to unsigned samples we have to raise each value
* by half the maximum value of a short (0xffff+1)/2 = 0x8000
*/
for (int i = 0; i < BUFFER_SIZE * 2; i++){
buffer[i] += 0x8000;
}
free_audio_stream_buffer(stream);
}
}
MusicRenderer::~MusicRenderer(){
stop_audio_stream(stream);
}
#endif
MusicPlayer::MusicPlayer():
volume(1.0),
out(new MusicRenderer()){
}
MusicPlayer::~MusicPlayer(){
}
void MusicPlayer::setRenderer(const ReferenceCount<MusicRenderer> & what){
this->out = what;
}
void MusicPlayer::play(){
out->play(*this);
}
void MusicPlayer::pause(){
out->pause();
}
void MusicPlayer::poll(){
out->poll(*this);
}
static const char * typeToExtension( int i ){
switch (i){
case 0 : return ".xm";
case 1 : return ".s3m";
case 2 : return ".it";
case 3 : return ".mod";
default : return "";
}
}
/* expects each sample to be 4 bytes, 2 bytes per sample * 2 channels */
DumbPlayer::DumbPlayer(string path){
music_file = loadDumbFile(path);
if (music_file == NULL){
std::ostringstream error;
error << "Could not load DUMB file " << path;
throw MusicException(__FILE__, __LINE__, error.str());
}
int n_channels = 2;
int position = 0;
renderer = duh_start_sigrenderer(music_file, 0, n_channels, position);
if (!renderer){
Global::debug(0) << "Could not create renderer" << std::endl;
throw Exception::Base(__FILE__, __LINE__);
}
}
void DumbPlayer::render(void * data, int samples){
double delta = 65536.0 / Sound::Info.frequency;
/* FIXME: use global music volume to scale the output here */
int n = duh_render(renderer, 16, 0, volume, delta, samples, data);
}
void DumbPlayer::setVolume(double volume){
this->volume = volume;
}
DumbPlayer::~DumbPlayer(){
duh_end_sigrenderer(renderer);
unload_duh(music_file);
}
DUH * DumbPlayer::loadDumbFile(string path){
DUH * what;
for (int i = 0; i < 4; i++){
/* the order of trying xm/s3m/it/mod matters because mod could be
* confused with one of the other formats, so load it last.
*/
switch (i){
case 0 : {
what = dumb_load_xm_quick(path.c_str());
break;
}
case 1 : {
what = dumb_load_s3m_quick(path.c_str());
break;
}
case 2 : {
what = dumb_load_it_quick(path.c_str());
break;
}
case 3 : {
what = dumb_load_mod_quick(path.c_str());
break;
}
}
if (what != NULL){
Global::debug(0) << "Loaded " << path << " type " << typeToExtension(i) << "(" << i << ")" << std::endl;
return what;
}
}
return NULL;
}
GMEPlayer::GMEPlayer(string path):
emulator(NULL){
gme_err_t fail = gme_open_file(path.c_str(), &emulator, Sound::Info.frequency);
if (fail != NULL){
Global::debug(0) << "GME load error for " << path << ": " << fail << std::endl;
throw MusicException(__FILE__, __LINE__, "Could not load GME file");
}
emulator->start_track(0);
Global::debug(0) << "Loaded GME file " << path << std::endl;
}
void GMEPlayer::render(void * stream, int length){
/* length/2 to convert bytes to short */
emulator->play(length * 2, (short*) stream);
if (emulator->track_ended()){
gme_info_t * info;
gme_track_info(emulator, &info, 0);
int intro = info->intro_length;
emulator->start_track(0);
// Global::debug(0) << "Seeking " << intro << "ms. Track length " << info->length << "ms" << std::endl;
/* skip past the intro if there is a loop */
if (info->loop_length != 0){
emulator->seek(intro);
}
}
/* scale for volume */
for (int i = 0; i < length * 2; i++){
short & sample = ((short *) stream)[i];
sample *= volume;
}
/*
short large = 0;
short small = 0;
for (int i = 0; i < length / 2; i++){
// ((short *) stream)[i] *= 2;
short z = ((short *) stream)[i];
if (z < small){
small = z;
}
if (z > large){
large = z;
}
}
Global::debug(0) << "Largest " << large << " Smallest " << small << std::endl;
*/
}
void GMEPlayer::setVolume(double volume){
this->volume = volume;
}
GMEPlayer::~GMEPlayer(){
delete emulator;
}
#ifdef HAVE_MP3_MPG123
/* initialize the mpg123 library and open up an mp3 file for reading */
static void initializeMpg123(mpg123_handle ** mp3, string path){
/* Initialize */
if (mpg123_init() != MPG123_OK){
throw MusicException(__FILE__, __LINE__, "Could not initialize mpg123");
}
try{
*mp3 = mpg123_new(NULL, NULL);
if (*mp3 == NULL){
throw MusicException(__FILE__,__LINE__, "Could not allocate mpg handle");
}
mpg123_format_none(*mp3);
/* allegro wants unsigned samples but mpg123 can't actually provide unsigned
* samples even though it has an enum for it, MPG123_ENC_UNSIGNED_16. this
* was rectified in 1.13.0 or something, but for now signed samples are ok.
*/
int error = mpg123_format(*mp3, Sound::Info.frequency, MPG123_STEREO, MPG123_ENC_SIGNED_16);
if (error != MPG123_OK){
Global::debug(0) << "Could not set format for mpg123 handle" << std::endl;
}
/* FIXME workaround for libmpg issues with "generic" decoder frequency not being set */
error = mpg123_open(*mp3, (char*) path.c_str());
if (error == -1){
std::ostringstream error;
error << "Could not open mpg123 file " << path << " error code " << error;
throw MusicException(__FILE__,__LINE__, error.str());
}
/* reading a frame is the only surefire way to get mpg123 to set the
* sampling_frequency which it needs to set the decoder a few lines below
*/
size_t dont_care;
unsigned char tempBuffer[4096];
error = mpg123_read(*mp3, tempBuffer, sizeof(tempBuffer), &dont_care);
if (!(error == MPG123_OK || error == MPG123_NEW_FORMAT)){
std::ostringstream error;
error << "Could not read mpg123 file " << path << " error code " << error;
throw MusicException(__FILE__,__LINE__, error.str());
}
mpg123_close(*mp3);
/* stream has progressed a little bit so reset it by opening it again */
error = mpg123_open(*mp3, (char*) path.c_str());
if (error == -1){
std::ostringstream error;
error << "Could not open mpg123 file " << path << " error code " << error;
throw MusicException(__FILE__,__LINE__, error.str());
}
/* FIXME end */
/* some of the native decoders aren't stable in older versions of mpg123
* so just use generic for now. 1.13.1 should work better
*/
error = mpg123_decoder(*mp3, "generic");
if (error != MPG123_OK){
std::ostringstream error;
error << "Could not use 'generic' mpg123 decoder for " << path << " error code " << error;
throw MusicException(__FILE__,__LINE__, error.str());
}
// Global::debug(0) << "mpg support " << mpg123_format_support(mp3, Sound::FREQUENCY, MPG123_ENC_SIGNED_16) << std::endl;
/*
double base, really, rva;
mpg123_getvolume(*mp3, &base, &really, &rva);
// Global::debug(0) << "mpg volume base " << base << " really " << really << " rva " << rva << std::endl;
base_volume = base;
long rate;
int channels, encoding;
mpg123_getformat(*mp3, &rate, &channels, &encoding);
// Global::debug(0) << path << " rate " << rate << " channels " << channels << " encoding " << encoding << std::endl;
*/
} catch (const MusicException & fail){
if (*mp3 != NULL){
mpg123_close(*mp3);
mpg123_delete(*mp3);
*mp3 = NULL;
}
mpg123_exit();
throw;
}
}
static const int MPG123_BUFFER_SIZE = 1 << 11;
Mp3Player::Mp3Player(string path):
mp3(NULL){
initializeMpg123(&mp3, path);
long rate = 0;
int channels = 0, encoding = 0;
mpg123_getformat(mp3, &rate, &channels, &encoding);
}
void Mp3Player::render(void * data, int samples){
/* buffer * 4 for 16 bits per sample * 2 samples for stereo */
size_t out = 0;
mpg123_read(mp3, (unsigned char *) data, samples * 4, &out);
/*
long rate;
int channels, encoding;
mpg123_getformat(mp3, &rate, &channels, &encoding);
Global::debug(0) << "rate " << rate << " channels " << channels << " encoding " << encoding << std::endl;
*/
}
void Mp3Player::setVolume(double volume){
mpg123_volume(mp3, volume);
/*
this->volume = volume;
// mpg123_volume(mp3, volume * base_volume / 5000);
mpg123_volume(mp3, 0.0001);
*/
// mpg123_volume(mp3, volume);
}
Mp3Player::~Mp3Player(){
mpg123_close(mp3);
mpg123_exit();
}
#endif /* MP3_MPG123 */
#ifdef HAVE_OGG
int OGG_BUFFER_SIZE = 1024 * 32;
OggPlayer::OggPlayer(string path):
path(path){
file = fopen(path.c_str(), "rb");
if (!file) {
throw MusicException(__FILE__, __LINE__, "Could not open file");
}
if (ov_open_callbacks(file, &ogg, 0, 0, OV_CALLBACKS_DEFAULT) != 0) {
fclose(file);
throw MusicException(__FILE__, __LINE__, "Could not open ogg");
}
vorbis_info * info = ov_info(&ogg, -1);
frequency = info->rate;
channels = info->channels;
bits = 16;
length = ov_pcm_total(&ogg, -1);
setRenderer(new MusicRenderer(info->rate, info->channels));
buffer = new OggPage();
buffer->buffer1.buffer = new char[OGG_BUFFER_SIZE];
// buffer->buffer2.buffer = new char[OGG_BUFFER_SIZE];
fillPage(&buffer->buffer1);
// fillPage(&buffer->buffer2);
// buffer->use = 0;
}
void OggPlayer::fillPage(OggPage::Page * page){
int dont_care;
page->position = 0;
page->max = 0;
while (page->max < OGG_BUFFER_SIZE){
/* ov_read might not read all available samples, I guess it stops
* reading on a page boundary. We just plow on through.
*/
int read = ov_read(&ogg, (char*) page->buffer + page->max, OGG_BUFFER_SIZE - page->max,
bigEndian(), 2, 1, &dont_care);
/* if we hit the end of the file then re-open it and keep reading */
if (read == 0){
ov_clear(&ogg);
file = fopen(path.c_str(), "rb");
if (!file){
throw MusicException(__FILE__, __LINE__, "Could not open file");
}
int ok = ov_open_callbacks(file, &ogg, 0, 0, OV_CALLBACKS_DEFAULT);
if (ok != 0){
fclose(file);
throw MusicException(__FILE__, __LINE__, "Could not open ogg");
}
} else if (read == OV_HOLE){
throw MusicException(__FILE__, __LINE__, "Garbage in ogg file");
} else if (read == OV_EBADLINK){
throw MusicException(__FILE__, __LINE__, "Invalid stream section in ogg");
} else if (read == OV_EINVAL){
throw MusicException(__FILE__, __LINE__, "File headers are corrupt in ogg");
} else {
page->max += read;
}
}
}
void OggPlayer::doRender(char * data, int bytes){
OggPage::Page & page = buffer->buffer1;
if (page.max - page.position >= bytes){
memcpy(data, page.buffer + page.position, bytes);
page.position += bytes;
} else {
/* copy the rest, fill the page, switch to the other buffer */
memcpy(data, page.buffer + page.position, page.max - page.position);
int at = page.max - page.position;
int rest = bytes - (page.max - page.position);
fillPage(&page);
doRender(data + at, rest);
}
}
void OggPlayer::render(void * data, int length){
doRender((char*) data, length * 4);
}
void OggPlayer::setVolume(double volume){
this->volume = volume;
// Mix_VolumeMusic(volume * MIX_MAX_VOLUME);
}
OggPlayer::~OggPlayer(){
/* ov_clear will close the file */
ov_clear(&ogg);
}
#endif /* OGG */
#ifdef HAVE_MP3_MAD
Mp3Player::Mp3Player(string path):
available(NULL),
bytesLeft(0),
position(0),
raw(NULL){
FILE * handle = fopen(path.c_str(), "rb");
if (!handle){
std::ostringstream out;
out << "Could not open mp3 file " << path;
throw MusicException(__FILE__, __LINE__, out.str());
}
fseek(handle, 0, SEEK_END);
rawLength = ftell(handle);
fseek(handle, 0, SEEK_SET);
raw = new unsigned char[rawLength];
int toRead = rawLength;
int where =0;
while (toRead > 0){
int got = fread(raw + where, 1, toRead, handle);
toRead -= got;
}
fclose(handle);
int rate = 44100, channels = 2;
discoverInfo(raw, rawLength, &rate, &channels);
setRenderer(new MusicRenderer(rate, channels));
Global::debug(0) << "Opened mp3 file " << path << " rate " << rate << " channels " << channels << std::endl;
mad_stream_init(&stream);
mad_frame_init(&frame);
mad_synth_init(&synth);
mad_stream_buffer(&stream, raw, rawLength);
fill(4);
}
/* read the first frame and get the rate and channels from the header.
* assume all other frames use the same rate and channels
*/
void Mp3Player::discoverInfo(unsigned char * raw, int length, int * rate, int * channels){
mad_frame frame;
mad_stream stream;
mad_frame_init(&frame);
mad_stream_init(&stream);
mad_stream_buffer(&stream, raw, length);
int ok = mad_header_decode(&frame.header, &stream);
while (ok == -1){
if (MAD_RECOVERABLE(stream.error)){
ok = mad_header_decode(&frame.header, &stream);
} else {
throw MusicException(__FILE__, __LINE__, "Could not decode mp3 frame");
}
}
*rate = frame.header.samplerate;
switch (frame.header.mode){
case MAD_MODE_SINGLE_CHANNEL: *channels = 1; break;
case MAD_MODE_DUAL_CHANNEL: *channels = 2; break;
case MAD_MODE_JOINT_STEREO: *channels = 2; break;
case MAD_MODE_STEREO: *channels = 2; break;
}
mad_frame_finish(&frame);
mad_stream_finish(&stream);
}
mad_flow Mp3Player::error(void * data, mad_stream * stream, mad_frame * frame){
if (MAD_RECOVERABLE(stream->error)){
return MAD_FLOW_CONTINUE;
}
throw MusicException(__FILE__, __LINE__, "Error decoding mp3 stream");
}
static inline signed int mad_scale(mad_fixed_t sample){
/* round */
sample += (1L << (MAD_F_FRACBITS - 16));
/* clip */
if (sample >= MAD_F_ONE)
sample = MAD_F_ONE - 1;
else if (sample < -MAD_F_ONE)
sample = -MAD_F_ONE;
/* quantize */
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
void Mp3Player::output(mad_header const * header, mad_pcm * pcm){
unsigned int channels = pcm->channels;
unsigned int samples = pcm->length;
mad_fixed_t const * left = pcm->samples[0];
mad_fixed_t const * right = pcm->samples[1];
unsigned short * out = new unsigned short[samples * 2];
for (unsigned int index = 0; index < samples; index++){
out[index * 2] = mad_scale(*left) & 0xffff;
out[index * 2 + 1] = mad_scale(*right) & 0xffff;
left += 1;
right += 1;
}
/* 2 channels * 2 bytes per sample */
pages.push_back(Data((char*) out, samples * 2 * 2));
}
mad_flow Mp3Player::input(void * data, mad_stream * stream){
/*
Mp3Player * player = (Mp3Player*) data;
if (!player->readMore){
return MAD_FLOW_STOP;
} else {
player->readMore = false;
}
int read = fread(player->raw, 1, RAW_SIZE, player->handle);
if (feof(player->handle)){
/ * start over * /
fseek(player->handle, 0, SEEK_SET);
}
mad_stream_buffer(stream, player->raw, read);
return MAD_FLOW_CONTINUE;
*/
return MAD_FLOW_CONTINUE;
}
void Mp3Player::fill(int frames){
for (int i = 0; i < frames; i++){
int headerError = mad_header_decode(&frame.header, &stream);
while (headerError == -1){
if (MAD_RECOVERABLE(stream.error)){
} else {
if (stream.error == MAD_ERROR_BUFLEN){
mad_stream_finish(&stream);
mad_frame_finish(&frame);
mad_synth_finish(&synth);
mad_stream_init(&stream);
mad_frame_init(&frame);
mad_synth_init(&synth);
mad_stream_buffer(&stream, raw, rawLength);
}
}
headerError = mad_header_decode(&frame.header, &stream);
}
mad_frame_decode(&frame, &stream);
mad_synth_frame(&synth, &frame);
output(&frame.header, &synth.pcm);
}
/*
readMore = true;
int result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
*/
bytesLeft = 0;
for (std::vector<Data>::iterator it = pages.begin(); it != pages.end(); it++){
bytesLeft += it->length;
}
// Global::debug(0) << "Read " << bytesLeft << std::endl;
delete[] available;
available = new char[bytesLeft];
position = 0;
int here = 0;
for (std::vector<Data>::iterator it = pages.begin(); it != pages.end(); it++){
memcpy(available + here, it->data, it->length);
here += it->length;
delete[] it->data;
}
pages.clear();
}
void Mp3Player::render(void * data, int length){
length *= 4;
while (length > 0){
int left = length;
if (left > bytesLeft){
left = bytesLeft;
}
memcpy(data, available + position, left);
length -= left;
bytesLeft -= left;
position += left;
data = ((char*) data) + left;
if (bytesLeft == 0){
fill(4);
}
}
}
void Mp3Player::setVolume(double volume){
/* TODO */
}
Mp3Player::~Mp3Player(){
delete[] raw;
delete[] available;
mad_stream_finish(&stream);
mad_frame_finish(&frame);
mad_synth_finish(&synth);
// mad_decoder_finish(&decoder);
}
#endif /* MP3_MAD */
}
diff --git a/util/music-player.h b/util/music-player.h
index 4fd2781c..404381cf 100644
--- a/util/music-player.h
+++ b/util/music-player.h
@@ -1,232 +1,234 @@
#ifndef _paintown_music_player_h
#define _paintown_music_player_h
#include <string>
#include <vector>
#include <stdio.h>
#ifdef USE_SDL
/* for Uint8 */
#include <SDL.h>
#include "sdl/mixer/SDL_mixer.h"
+#include "audio.h"
#endif
#ifdef HAVE_MP3_MPG123
#include <mpg123.h>
#endif
#ifdef HAVE_OGG
#include <vorbis/vorbisfile.h>
#endif
#ifdef HAVE_MP3_MAD
#include <mad.h>
#endif
#include "pointer.h"
struct DUH;
struct DUH_SIGRENDERER;
#ifdef USE_ALLEGRO
struct AUDIOSTREAM;
#endif
struct LOGG_Stream;
class Music_Emu;
#ifdef USE_ALLEGRO5
struct ALLEGRO_AUDIO_STREAM;
struct ALLEGRO_EVENT_QUEUE;
#endif
namespace Util{
class MusicPlayer;
/* implemented by some backend: allegro4/sdl/allergo5 */
class MusicRenderer{
public:
MusicRenderer();
MusicRenderer(int frequency, int channels);
virtual ~MusicRenderer();
void poll(MusicPlayer & player);
void play(MusicPlayer & player);
void pause();
protected:
void create(int frequency, int channels);
#ifdef USE_SDL
static void mixer(void * arg, Uint8 * stream, int length);
void fill(MusicPlayer * player);
void read(MusicPlayer * player, Uint8 * stream, int bytes);
- SDL_AudioCVT convert;
+ AudioConverter convert;
+ // SDL_AudioCVT convert;
Uint8 * data;
int position;
int converted;
#endif
#ifdef USE_ALLEGRO
AUDIOSTREAM * stream;
#endif
#ifdef USE_ALLEGRO5
ALLEGRO_AUDIO_STREAM * stream;
ALLEGRO_EVENT_QUEUE * queue;
#endif
};
class MusicPlayer{
public:
MusicPlayer();
virtual void play();
virtual void poll();
virtual void pause();
virtual void setVolume(double volume) = 0;
virtual ~MusicPlayer();
/* length is in samples not bytes.
* this function must produce samples that are
* signed
* 16-bit
* use the native endian of the machine
* dual-channel
*
* Which means each sample should be 4 bytes
* 2 bytes * 2 channels
*/
virtual void render(void * stream, int length) = 0;
virtual inline double getVolume() const {
return volume;
}
virtual const ReferenceCount<MusicRenderer> & getRenderer() const {
return out;
}
virtual void setRenderer(const ReferenceCount<MusicRenderer> & what);
protected:
double volume;
ReferenceCount<MusicRenderer> out;
};
/* uses the GME library, plays nintendo music files and others */
class GMEPlayer: public MusicPlayer {
public:
GMEPlayer(std::string path);
virtual void setVolume(double volume);
virtual ~GMEPlayer();
virtual void render(void * stream, int length);
protected:
Music_Emu * emulator;
};
#ifdef HAVE_OGG
struct OggPage{
struct Page{
int position;
int max;
char * buffer;
~Page(){
delete[] buffer;
}
};
Page buffer1;
// Page buffer2;
// int use;
};
/* Maybe have some common sdl mixer class that this can inherit? */
class OggPlayer: public MusicPlayer {
public:
OggPlayer(std::string path);
virtual void setVolume(double volume);
virtual void render(void * stream, int length);
virtual ~OggPlayer();
protected:
void fillPage(OggPage::Page * page);
void doRender(char * data, int bytes);
FILE* file;
std::string path;
OggVorbis_File ogg;
ReferenceCount<OggPage> buffer;
int frequency;
int channels;
int bits;
ogg_int64_t length;
};
#endif
#if defined (HAVE_MP3_MPG123) || defined (HAVE_MP3_MAD)
/* Interface for mp3s */
class Mp3Player: public MusicPlayer {
public:
Mp3Player(std::string path);
virtual void setVolume(double volume);
virtual void render(void * data, int length);
virtual ~Mp3Player();
protected:
#ifdef HAVE_MP3_MPG123
mpg123_handle * mp3;
double base_volume;
#elif HAVE_MP3_MAD
void output(mad_header const * header, mad_pcm * pcm);
static mad_flow error(void * data, mad_stream * stream, mad_frame * frame);
static mad_flow input(void * data, mad_stream * stream);
void discoverInfo(unsigned char * raw, int length, int * rate, int * channels);
void fill(int frames);
mad_stream stream;
mad_frame frame;
mad_synth synth;
char * available;
int bytesLeft;
int position;
bool readMore;
struct Data{
Data():
data(NULL),
length(0){
}
Data(char * data, int length):
data(data), length(length){
}
~Data(){
}
char * data;
int length;
};
std::vector<Data> pages;
unsigned char * raw;
int rawLength;
#endif
};
#endif
/* interface to DUMB, plays mod/s3m/xm/it */
class DumbPlayer: public MusicPlayer {
public:
DumbPlayer(std::string path);
virtual void setVolume(double volume);
virtual void render(void * data, int samples);
virtual ~DumbPlayer();
protected:
DUH * loadDumbFile(std::string path);
protected:
DUH * music_file;
DUH_SIGRENDERER * renderer;
};
}
#endif
diff --git a/util/sfl/SConscript b/util/sfl/SConscript
index eeb5bca6..9130a830 100644
--- a/util/sfl/SConscript
+++ b/util/sfl/SConscript
@@ -1,57 +1,14 @@
Import('use')
-source = Split("""
-sflbits.c
-sflcomp.c
-sflcons.c
-sflconv.c
-sflcryp.c
-sflcvbs.c
-sflcvdp.c
-sflcvds.c
-sflcvns.c
-sflcvsb.c
-sflcvsd.c
-sflcvsn.c
-sflcvtp.c
-sflcvts.c
-sfldbio.c
-sfldir.c
-sflenv.c
-sflexdr.c
-sflfile.c
-sflfind.c
-sflfort.c
-sflhttp.c
-sflini.c
-sfllang.c
-sfllbuf.c
-sfllist.c
-sflmath.c
-sflmem.c
-sflmesg.c
-sflmime.c
-sflnode.c
-sflprint.c
-sflslot.c
-sflstr.c
-sflsymb.c
-sflsyst.c
-sfltok.c
-sfltree.c
-sfltron.c
-sflxml.c
-sfluid.c
-sfldate.c
+source = Split("""sflbits.c sflcomp.c sflcons.c sflconv.c sflcryp.c sflcvbs.c
+sflcvdp.c sflcvds.c sflcvns.c sflcvsb.c sflcvsd.c sflcvsn.c sflcvtp.c sflcvts.c
+sfldbio.c sfldir.c sflenv.c sflexdr.c sflfile.c sflfind.c sflfort.c sflhttp.c
+sflini.c sfllang.c sfllbuf.c sfllist.c sflmath.c sflmem.c sflmesg.c sflmime.c
+sflnode.c sflprint.c sflslot.c sflstr.c sflsymb.c sflsyst.c sfltok.c sfltree.c
+sfltron.c sflxml.c sfluid.c sfldate.c
""")
-ignored = Split("""
-sflcvst.c
-sflxmll.c
-sflproc.c
-sflsock.c
-sflmysql.c
-""")
+ignored = Split("""sflcvst.c sflxmll.c sflproc.c sflsock.c sflmysql.c""")
x = use.StaticLibrary('sfl', source)
Return('x')
diff --git a/util/sox/SConscript b/util/sox/SConscript
new file mode 100644
index 00000000..2efc0e38
--- /dev/null
+++ b/util/sox/SConscript
@@ -0,0 +1,7 @@
+Import('use')
+
+source = Split("""src/formats.c
+""")
+
+x = use.StaticLibrary('sox', source)
+Return('x')
diff --git a/util/sox/src/effects.h b/util/sox/src/effects.h
new file mode 100644
index 00000000..92fff0b3
--- /dev/null
+++ b/util/sox/src/effects.h
@@ -0,0 +1,95 @@
+/* This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* FIXME: generate this list automatically */
+
+ EFFECT(allpass)
+ EFFECT(band)
+ EFFECT(bandpass)
+ EFFECT(bandreject)
+ EFFECT(bass)
+ EFFECT(bend)
+ EFFECT(biquad)
+ EFFECT(chorus)
+ EFFECT(channels)
+ EFFECT(compand)
+ EFFECT(contrast)
+ EFFECT(crop)
+ EFFECT(dcshift)
+ EFFECT(deemph)
+ EFFECT(delay)
+ EFFECT(dft_filter) /* abstract */
+ EFFECT(dither)
+ EFFECT(divide)
+ EFFECT(earwax)
+ EFFECT(echo)
+ EFFECT(echos)
+ EFFECT(equalizer)
+ EFFECT(fade)
+ EFFECT(filter)
+ EFFECT(fir)
+ EFFECT(firfit)
+ EFFECT(flanger)
+ EFFECT(gain)
+ EFFECT(highpass)
+ EFFECT(input)
+ EFFECT(key)
+#ifdef HAVE_LADSPA_H
+ EFFECT(ladspa)
+#endif
+ EFFECT(loudness)
+ EFFECT(lowpass)
+ EFFECT(mcompand)
+ EFFECT(mixer)
+ EFFECT(noiseprof)
+ EFFECT(noisered)
+ EFFECT(norm)
+ EFFECT(oops)
+ EFFECT(output)
+ EFFECT(overdrive)
+ EFFECT(pad)
+ EFFECT(pan)
+ EFFECT(phaser)
+ EFFECT(pitch)
+ EFFECT(polyphase)
+ EFFECT(rabbit)
+ EFFECT(rate)
+ EFFECT(remix)
+ EFFECT(repeat)
+ EFFECT(resample)
+ EFFECT(reverb)
+ EFFECT(reverse)
+ EFFECT(riaa)
+ EFFECT(silence)
+ EFFECT(sinc)
+#ifdef HAVE_PNG
+ EFFECT(spectrogram)
+#endif
+ EFFECT(speed)
+#ifdef HAVE_SPEEXDSP
+ EFFECT(speexdsp)
+#endif
+ EFFECT(splice)
+ EFFECT(stat)
+ EFFECT(stats)
+ EFFECT(stretch)
+ EFFECT(swap)
+ EFFECT(synth)
+ EFFECT(tempo)
+ EFFECT(treble)
+ EFFECT(tremolo)
+ EFFECT(trim)
+ EFFECT(vad)
+ EFFECT(vol)
diff --git a/util/sox/src/formats.c b/util/sox/src/formats.c
new file mode 100644
index 00000000..3a6ac33a
--- /dev/null
+++ b/util/sox/src/formats.c
@@ -0,0 +1,1263 @@
+/* Implements the public API for using libSoX file formats.
+ * All public functions & data are prefixed with sox_ .
+ *
+ * (c) 2005-8 Chris Bagwell and SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "sox_i.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef HAVE_IO_H
+ #include <io.h>
+#endif
+
+#if HAVE_MAGIC
+ #include <magic.h>
+#endif
+
+#define AUTO_DETECT_SIZE 256
+
+static char const * auto_detect_format(sox_format_t * ft, char const * ext)
+{
+ char data[AUTO_DETECT_SIZE];
+ size_t len = lsx_readbuf(ft, data, sizeof(data));
+ #define CHECK(type, p2, l2, d2, p1, l1, d1) if (len >= p1 + l1 && \
+ !memcmp(data + p1, d1, (size_t)l1) && !memcmp(data + p2, d2, (size_t)l2)) return #type;
+ CHECK(voc , 0, 0, "" , 0, 20, "Creative Voice File\x1a")
+ CHECK(smp , 0, 0, "" , 0, 17, "SOUND SAMPLE DATA")
+ CHECK(wve , 0, 0, "" , 0, 15, "ALawSoundFile**")
+ CHECK(gsrt , 0, 0, "" , 16, 9, "ring.bin")
+ CHECK(amr-wb, 0, 0, "" , 0, 9, "#!AMR-WB\n")
+ CHECK(prc , 0, 0, "" , 0, 8, "\x37\x00\x00\x10\x6d\x00\x00\x10")
+ CHECK(sph , 0, 0, "" , 0, 7, "NIST_1A")
+ CHECK(amr-nb, 0, 0, "" , 0, 6, "#!AMR\n")
+ CHECK(txw , 0, 0, "" , 0, 6, "LM8953")
+ CHECK(sndt , 0, 0, "" , 0, 6, "SOUND\x1a")
+ CHECK(vorbis, 0, 4, "OggS" , 29, 6, "vorbis")
+ CHECK(speex , 0, 4, "OggS" , 28, 6, "Speex")
+ CHECK(hcom ,65, 4, "FSSD" , 128,4, "HCOM")
+ CHECK(wav , 0, 4, "RIFF" , 8, 4, "WAVE")
+ CHECK(wav , 0, 4, "RIFX" , 8, 4, "WAVE")
+ CHECK(aiff , 0, 4, "FORM" , 8, 4, "AIFF")
+ CHECK(aifc , 0, 4, "FORM" , 8, 4, "AIFC")
+ CHECK(8svx , 0, 4, "FORM" , 8, 4, "8SVX")
+ CHECK(maud , 0, 4, "FORM" , 8, 4, "MAUD")
+ CHECK(xa , 0, 0, "" , 0, 4, "XA\0\0")
+ CHECK(xa , 0, 0, "" , 0, 4, "XAI\0")
+ CHECK(xa , 0, 0, "" , 0, 4, "XAJ\0")
+ CHECK(au , 0, 0, "" , 0, 4, ".snd")
+ CHECK(au , 0, 0, "" , 0, 4, "dns.")
+ CHECK(au , 0, 0, "" , 0, 4, "\0ds.")
+ CHECK(au , 0, 0, "" , 0, 4, ".sd\0")
+ CHECK(flac , 0, 0, "" , 0, 4, "fLaC")
+ CHECK(avr , 0, 0, "" , 0, 4, "2BIT")
+ CHECK(caf , 0, 0, "" , 0, 4, "caff")
+ CHECK(wv , 0, 0, "" , 0, 4, "wvpk")
+ CHECK(paf , 0, 0, "" , 0, 4, " paf")
+ CHECK(sf , 0, 0, "" , 0, 4, "\144\243\001\0")
+ CHECK(sf , 0, 0, "" , 0, 4, "\0\001\243\144")
+ CHECK(sf , 0, 0, "" , 0, 4, "\144\243\002\0")
+ CHECK(sf , 0, 0, "" , 0, 4, "\0\002\243\144")
+ CHECK(sf , 0, 0, "" , 0, 4, "\144\243\003\0")
+ CHECK(sf , 0, 0, "" , 0, 4, "\0\003\243\144")
+ CHECK(sf , 0, 0, "" , 0, 4, "\144\243\004\0")
+ CHECK(sox , 0, 0, "" , 0, 4, ".SoX")
+ CHECK(sox , 0, 0, "" , 0, 4, "XoS.")
+
+ if (ext && !strcasecmp(ext, "snd"))
+ CHECK(sndr , 7, 1, "" , 0, 2, "\0")
+ #undef CHECK
+
+#if HAVE_MAGIC
+ if (sox_globals.use_magic) {
+ static magic_t magic;
+ char const * filetype = NULL;
+ if (!magic) {
+ magic = magic_open(MAGIC_MIME | MAGIC_SYMLINK);
+ if (magic)
+ magic_load(magic, NULL);
+ }
+ if (magic)
+ filetype = magic_buffer(magic, data, sizeof(data));
+ if (filetype && strncmp(filetype, "application/octet-stream", (size_t)24) &&
+ !lsx_strends(filetype, "/unknown") &&
+ strncmp(filetype, "text/plain", (size_t)10) )
+ return filetype;
+ else if (filetype)
+ lsx_debug("libmagic detected %s", filetype);
+ }
+#endif
+ return NULL;
+}
+
+sox_encodings_info_t const sox_encodings_info[] = {
+ {0 , "n/a" , "Unknown or not applicable"},
+ {0 , "Signed PCM" , "Signed Integer PCM"},
+ {0 , "Unsigned PCM" , "Unsigned Integer PCM"},
+ {0 , "F.P. PCM" , "Floating Point PCM"},
+ {0 , "F.P. PCM" , "Floating Point (text) PCM"},
+ {0 , "FLAC" , "FLAC"},
+ {0 , "HCOM" , "HCOM"},
+ {0 , "WavPack" , "WavPack"},
+ {0 , "F.P. WavPack" , "Floating Point WavPack"},
+ {SOX_LOSSY1, "u-law" , "u-law"},
+ {SOX_LOSSY1, "A-law" , "A-law"},
+ {SOX_LOSSY1, "G.721 ADPCM" , "G.721 ADPCM"},
+ {SOX_LOSSY1, "G.723 ADPCM" , "G.723 ADPCM"},
+ {SOX_LOSSY1, "CL ADPCM (8)" , "CL ADPCM (from 8-bit)"},
+ {SOX_LOSSY1, "CL ADPCM (16)", "CL ADPCM (from 16-bit)"},
+ {SOX_LOSSY1, "MS ADPCM" , "MS ADPCM"},
+ {SOX_LOSSY1, "IMA ADPCM" , "IMA ADPCM"},
+ {SOX_LOSSY1, "OKI ADPCM" , "OKI ADPCM"},
+ {SOX_LOSSY1, "DPCM" , "DPCM"},
+ {0 , "DWVW" , "DWVW"},
+ {0 , "DWVWN" , "DWVWN"},
+ {SOX_LOSSY2, "GSM" , "GSM"},
+ {SOX_LOSSY2, "MPEG audio" , "MPEG audio (layer I, II or III)"},
+ {SOX_LOSSY2, "Vorbis" , "Vorbis"},
+ {SOX_LOSSY2, "AMR-WB" , "AMR-WB"},
+ {SOX_LOSSY2, "AMR-NB" , "AMR-NB"},
+ {SOX_LOSSY2, "CVSD" , "CVSD"},
+ {SOX_LOSSY2, "LPC10" , "LPC10"},
+};
+
+assert_static(array_length(sox_encodings_info) == SOX_ENCODINGS,
+ SIZE_MISMATCH_BETWEEN_sox_encoding_t_AND_sox_encodings_info);
+
+unsigned sox_precision(sox_encoding_t encoding, unsigned bits_per_sample)
+{
+ switch (encoding) {
+ case SOX_ENCODING_DWVW: return bits_per_sample;
+ case SOX_ENCODING_DWVWN: return !bits_per_sample? 16: 0; /* ? */
+ case SOX_ENCODING_HCOM: return !(bits_per_sample & 7) && (bits_per_sample >> 3) - 1 < 1? bits_per_sample: 0;
+ case SOX_ENCODING_WAVPACK:
+ case SOX_ENCODING_FLAC: return !(bits_per_sample & 7) && (bits_per_sample >> 3) - 1 < 4? bits_per_sample: 0;
+ case SOX_ENCODING_SIGN2: return bits_per_sample <= 32? bits_per_sample : 0;
+ case SOX_ENCODING_UNSIGNED: return !(bits_per_sample & 7) && (bits_per_sample >> 3) - 1 < 4? bits_per_sample: 0;
+
+ case SOX_ENCODING_ALAW: return bits_per_sample == 8? 13: 0;
+ case SOX_ENCODING_ULAW: return bits_per_sample == 8? 14: 0;
+
+ case SOX_ENCODING_CL_ADPCM: return bits_per_sample? 8: 0;
+ case SOX_ENCODING_CL_ADPCM16: return bits_per_sample == 4? 13: 0;
+ case SOX_ENCODING_MS_ADPCM: return bits_per_sample == 4? 14: 0;
+ case SOX_ENCODING_IMA_ADPCM: return bits_per_sample == 4? 13: 0;
+ case SOX_ENCODING_OKI_ADPCM: return bits_per_sample == 4? 12: 0;
+ case SOX_ENCODING_G721: return bits_per_sample == 4? 12: 0;
+ case SOX_ENCODING_G723: return bits_per_sample == 3? 8:
+ bits_per_sample == 5? 14: 0;
+ case SOX_ENCODING_CVSD: return bits_per_sample == 1? 16: 0;
+ case SOX_ENCODING_DPCM: return bits_per_sample; /* ? */
+
+ case SOX_ENCODING_MP3: return 0; /* Accept the precision returned by the format. */
+
+ case SOX_ENCODING_GSM:
+ case SOX_ENCODING_VORBIS:
+ case SOX_ENCODING_AMR_WB:
+ case SOX_ENCODING_AMR_NB:
+ case SOX_ENCODING_LPC10: return !bits_per_sample? 16: 0;
+
+ case SOX_ENCODING_WAVPACKF:
+ case SOX_ENCODING_FLOAT: return bits_per_sample == 32 ? 24: bits_per_sample == 64 ? 53: 0;
+ case SOX_ENCODING_FLOAT_TEXT: return !bits_per_sample? 53: 0;
+
+ case SOX_ENCODINGS:
+ case SOX_ENCODING_UNKNOWN: break;
+ }
+ return 0;
+}
+
+void sox_init_encodinginfo(sox_encodinginfo_t * e)
+{
+ e->reverse_bytes = SOX_OPTION_DEFAULT;
+ e->reverse_nibbles = SOX_OPTION_DEFAULT;
+ e->reverse_bits = SOX_OPTION_DEFAULT;
+ e->compression = HUGE_VAL;
+}
+
+/*--------------------------------- Comments ---------------------------------*/
+
+size_t sox_num_comments(sox_comments_t comments)
+{
+ size_t result = 0;
+ if (!comments)
+ return 0;
+ while (*comments++)
+ ++result;
+ return result;
+}
+
+void sox_append_comment(sox_comments_t * comments, char const * comment)
+{
+ size_t n = sox_num_comments(*comments);
+ *comments = lsx_realloc(*comments, (n + 2) * sizeof(**comments));
+ assert(comment);
+ (*comments)[n++] = lsx_strdup(comment);
+ (*comments)[n] = 0;
+}
+
+void sox_append_comments(sox_comments_t * comments, char const * comment)
+{
+ char * end;
+ if (comment) {
+ while ((end = strchr(comment, '\n'))) {
+ size_t len = end - comment;
+ char * c = lsx_malloc((len + 1) * sizeof(*c));
+ strncpy(c, comment, len);
+ c[len] = '\0';
+ sox_append_comment(comments, c);
+ comment += len + 1;
+ free(c);
+ }
+ if (*comment)
+ sox_append_comment(comments, comment);
+ }
+}
+
+sox_comments_t sox_copy_comments(sox_comments_t comments)
+{
+ sox_comments_t result = 0;
+
+ if (comments) while (*comments)
+ sox_append_comment(&result, *comments++);
+ return result;
+}
+
+void sox_delete_comments(sox_comments_t * comments)
+{
+ sox_comments_t p = *comments;
+
+ if (p) while (*p)
+ free(*p++);
+ free(*comments);
+ *comments = 0;
+}
+
+char * lsx_cat_comments(sox_comments_t comments)
+{
+ sox_comments_t p = comments;
+ size_t len = 0;
+ char * result;
+
+ if (p) while (*p)
+ len += strlen(*p++) + 1;
+
+ result = lsx_calloc(len? len : 1, sizeof(*result));
+
+ if ((p = comments) && *p) {
+ strcpy(result, *p);
+ while (*++p)
+ strcat(strcat(result, "\n"), *p);
+ }
+ return result;
+}
+
+char const * sox_find_comment(sox_comments_t comments, char const * id)
+{
+ size_t len = strlen(id);
+
+ if (comments) for (;*comments; ++comments)
+ if (!strncasecmp(*comments, id, len) && (*comments)[len] == '=')
+ return *comments + len + 1;
+ return NULL;
+}
+
+static void set_endiannesses(sox_format_t * ft)
+{
+ if (ft->encoding.opposite_endian)
+ ft->encoding.reverse_bytes = (ft->handler.flags & SOX_FILE_ENDIAN)?
+ !(ft->handler.flags & SOX_FILE_ENDBIG) != MACHINE_IS_BIGENDIAN : sox_true;
+ else if (ft->encoding.reverse_bytes == SOX_OPTION_DEFAULT)
+ ft->encoding.reverse_bytes = (ft->handler.flags & SOX_FILE_ENDIAN)?
+ !(ft->handler.flags & SOX_FILE_ENDBIG) == MACHINE_IS_BIGENDIAN : sox_false;
+
+ /* FIXME: Change reports to suitable warnings if trying
+ * to override something that can't be overridden. */
+
+ if (ft->handler.flags & SOX_FILE_ENDIAN) {
+ if (ft->encoding.reverse_bytes == (sox_option_t)
+ (!(ft->handler.flags & SOX_FILE_ENDBIG) != MACHINE_IS_BIGENDIAN))
+ lsx_report("`%s': overriding file-type byte-order", ft->filename);
+ } else if (ft->encoding.reverse_bytes == sox_true)
+ lsx_report("`%s': overriding machine byte-order", ft->filename);
+
+ if (ft->encoding.reverse_bits == SOX_OPTION_DEFAULT)
+ ft->encoding.reverse_bits = !!(ft->handler.flags & SOX_FILE_BIT_REV);
+ else if (ft->encoding.reverse_bits == !(ft->handler.flags & SOX_FILE_BIT_REV))
+ lsx_report("`%s': overriding file-type bit-order", ft->filename);
+
+ if (ft->encoding.reverse_nibbles == SOX_OPTION_DEFAULT)
+ ft->encoding.reverse_nibbles = !!(ft->handler.flags & SOX_FILE_NIB_REV);
+ else
+ if (ft->encoding.reverse_nibbles == !(ft->handler.flags & SOX_FILE_NIB_REV))
+ lsx_report("`%s': overriding file-type nibble-order", ft->filename);
+}
+
+static sox_bool is_seekable(sox_format_t const * ft)
+{
+ struct stat st;
+
+ assert(ft);
+ if (!ft->fp)
+ return sox_false;
+ fstat(fileno(ft->fp), &st);
+ return ((st.st_mode & S_IFMT) == S_IFREG);
+}
+
+/* check that all settings have been given */
+static int sox_checkformat(sox_format_t * ft)
+{
+ ft->sox_errno = SOX_SUCCESS;
+
+ if (!ft->signal.rate) {
+ lsx_fail_errno(ft,SOX_EFMT,"sampling rate was not specified");
+ return SOX_EOF;
+ }
+ if (!ft->signal.precision) {
+ lsx_fail_errno(ft,SOX_EFMT,"data encoding was not specified");
+ return SOX_EOF;
+ }
+ return SOX_SUCCESS;
+}
+
+static sox_bool is_url(char const * text) /* detects only wget-supported URLs */
+{
+ return !(
+ strncasecmp(text, "http:" , (size_t)5) &&
+ strncasecmp(text, "https:", (size_t)6) &&
+ strncasecmp(text, "ftp:" , (size_t)4));
+}
+
+static int xfclose(FILE * file, lsx_io_type io_type)
+{
+ return
+#ifdef HAVE_POPEN
+ io_type != lsx_io_file? pclose(file) :
+#endif
+ fclose(file);
+}
+
+static FILE * xfopen(char const * identifier, char const * mode, lsx_io_type * io_type)
+{
+ *io_type = lsx_io_file;
+
+ if (*identifier == '|') {
+ FILE * f = NULL;
+#ifdef HAVE_POPEN
+ f = popen(identifier + 1, "r");
+ *io_type = lsx_io_pipe;
+#else
+ lsx_fail("this build of SoX cannot open pipes");
+#endif
+ return f;
+ }
+ else if (is_url(identifier)) {
+ FILE * f = NULL;
+#ifdef HAVE_POPEN
+ char const * const command_format = "wget --no-check-certificate -q -O- \"%s\"";
+ char * command = lsx_malloc(strlen(command_format) + strlen(identifier));
+ sprintf(command, command_format, identifier);
+ f = popen(command, "r");
+ free(command);
+ *io_type = lsx_io_url;
+#else
+ lsx_fail("this build of SoX cannot open URLs");
+#endif
+ return f;
+ }
+ return fopen(identifier, mode);
+}
+
+/* Hack to rewind pipes (a small amount).
+ * Works by resetting the FILE buffer pointer */
+static void UNUSED rewind_pipe(FILE * fp)
+{
+/* _FSTDIO is for Torek stdio (i.e. most BSD-derived libc's)
+ * In theory, we no longer need to check _NEWLIB_VERSION or __APPLE__ */
+#if defined _FSTDIO || defined _NEWLIB_VERSION || defined __APPLE__
+ fp->_p -= AUTO_DETECT_SIZE;
+ fp->_r += AUTO_DETECT_SIZE;
+#elif defined __GLIBC__
+ fp->_IO_read_ptr = fp->_IO_read_base;
+#elif defined _MSC_VER || defined __MINGW_H || defined _ISO_STDIO_ISO_H
+ fp->_ptr = fp->_base;
+#else
+ /* To fix this #error, either simply remove the #error line and live without
+ * file-type detection with pipes, or add support for your compiler in the
+ * lines above. Test with cat monkey.au | ./sox --info - */
+ #error FIX NEEDED HERE
+ #define NO_REWIND_PIPE
+ (void)fp;
+#endif
+}
+
+static sox_format_t * open_read(
+ char const * path,
+ void * buffer UNUSED,
+ size_t buffer_size UNUSED,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype)
+{
+ sox_format_t * ft = lsx_calloc(1, sizeof(*ft));
+ sox_format_handler_t const * handler;
+ char const * const io_types[] = {"file", "pipe", "file URL"};
+ char const * type = "";
+ size_t input_bufsiz = sox_globals.input_bufsiz?
+ sox_globals.input_bufsiz : sox_globals.bufsiz;
+
+ if (filetype) {
+ if (!(handler = sox_find_format(filetype, sox_false))) {
+ lsx_fail("no handler for given file type `%s'", filetype);
+ goto error;
+ }
+ ft->handler = *handler;
+ }
+
+ if (!(ft->handler.flags & SOX_FILE_NOSTDIO)) {
+ if (!strcmp(path, "-")) { /* Use stdin if the filename is "-" */
+ if (sox_globals.stdin_in_use_by) {
+ lsx_fail("`-' (stdin) already in use by `%s'", sox_globals.stdin_in_use_by);
+ goto error;
+ }
+ sox_globals.stdin_in_use_by = "audio input";
+ SET_BINARY_MODE(stdin);
+ ft->fp = stdin;
+ }
+ else {
+ ft->fp =
+#ifdef HAVE_FMEMOPEN
+ buffer? fmemopen(buffer, buffer_size, "rb") :
+#endif
+ xfopen(path, "rb", &ft->io_type);
+ type = io_types[ft->io_type];
+ if (ft->fp == NULL) {
+ lsx_fail("can't open input %s `%s': %s", type, path, strerror(errno));
+ goto error;
+ }
+ }
+ if (setvbuf (ft->fp, NULL, _IOFBF, sizeof(char) * input_bufsiz)) {
+ lsx_fail("Can't set read buffer");
+ goto error;
+ }
+ ft->seekable = is_seekable(ft);
+ }
+
+ if (!filetype) {
+ if (ft->seekable) {
+ filetype = auto_detect_format(ft, lsx_find_file_extension(path));
+ lsx_rewind(ft);
+ }
+#ifndef NO_REWIND_PIPE
+ else if (!(ft->handler.flags & SOX_FILE_NOSTDIO) &&
+ input_bufsiz >= AUTO_DETECT_SIZE) {
+ filetype = auto_detect_format(ft, lsx_find_file_extension(path));
+ rewind_pipe(ft->fp);
+ ft->tell_off = 0;
+ }
+#endif
+
+ if (filetype) {
+ lsx_report("detected file format type `%s'", filetype);
+ if (!(handler = sox_find_format(filetype, sox_false))) {
+ lsx_fail("no handler for detected file type `%s'", filetype);
+ goto error;
+ }
+ }
+ else {
+ if (ft->io_type == lsx_io_pipe) {
+ filetype = "sox"; /* With successful pipe rewind, this isn't useful */
+ lsx_report("assuming input pipe `%s' has file-type `sox'", path);
+ }
+ else if (!(filetype = lsx_find_file_extension(path))) {
+ lsx_fail("can't determine type of %s `%s'", type, path);
+ goto error;
+ }
+ if (!(handler = sox_find_format(filetype, sox_true))) {
+ lsx_fail("no handler for file extension `%s'", filetype);
+ goto error;
+ }
+ }
+ ft->handler = *handler;
+ if (ft->handler.flags & SOX_FILE_NOSTDIO) {
+ xfclose(ft->fp, ft->io_type);
+ ft->fp = NULL;
+ }
+ }
+ if (!ft->handler.startread && !ft->handler.read) {
+ lsx_fail("file type `%s' isn't readable", filetype);
+ goto error;
+ }
+
+ ft->mode = 'r';
+ ft->filetype = lsx_strdup(filetype);
+ ft->filename = lsx_strdup(path);
+ if (signal)
+ ft->signal = *signal;
+
+ if (encoding)
+ ft->encoding = *encoding;
+ else sox_init_encodinginfo(&ft->encoding);
+ set_endiannesses(ft);
+
+ if ((ft->handler.flags & SOX_FILE_DEVICE) && !(ft->handler.flags & SOX_FILE_PHONY))
+ lsx_set_signal_defaults(ft);
+
+ ft->priv = lsx_calloc(1, ft->handler.priv_size);
+ /* Read and write starters can change their formats. */
+ if (ft->handler.startread && (*ft->handler.startread)(ft) != SOX_SUCCESS) {
+ lsx_fail("can't open input %s `%s': %s", type, ft->filename, ft->sox_errstr);
+ goto error;
+ }
+
+ /* Fill in some defaults: */
+ if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample))
+ ft->signal.precision = sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample);
+ if (!(ft->handler.flags & SOX_FILE_PHONY) && !ft->signal.channels)
+ ft->signal.channels = 1;
+
+ if (sox_checkformat(ft) != SOX_SUCCESS) {
+ lsx_fail("bad input format for %s `%s': %s", type, ft->filename, ft->sox_errstr);
+ goto error;
+ }
+
+ if (signal) {
+ if (signal->rate && signal->rate != ft->signal.rate)
+ lsx_warn("can't set sample rate %g; using %g", signal->rate, ft->signal.rate);
+ if (signal->channels && signal->channels != ft->signal.channels)
+ lsx_warn("can't set %u channels; using %u", signal->channels, ft->signal.channels);
+ }
+ return ft;
+
+error:
+ if (ft->fp && ft->fp != stdin)
+ xfclose(ft->fp, ft->io_type);
+ free(ft->priv);
+ free(ft->filename);
+ free(ft->filetype);
+ free(ft);
+ return NULL;
+}
+
+sox_format_t * sox_open_read(
+ char const * path,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype)
+{
+ return open_read(path, NULL, (size_t)0, signal, encoding, filetype);
+}
+
+sox_format_t * sox_open_mem_read(
+ void * buffer,
+ size_t buffer_size,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype)
+{
+ return open_read("", buffer, buffer_size, signal,encoding,filetype);
+}
+
+sox_bool sox_format_supports_encoding(
+ char const * path,
+ char const * filetype,
+ sox_encodinginfo_t const * encoding)
+{
+ #define enc_arg(T) (T)handler->write_formats[i++]
+ sox_bool is_file_extension = filetype == NULL;
+ sox_format_handler_t const * handler;
+ unsigned i = 0, s;
+ sox_encoding_t e;
+
+ assert(path);
+ assert(encoding);
+ if (!filetype)
+ filetype = lsx_find_file_extension(path);
+
+ if (!filetype || !(handler = sox_find_format(filetype, is_file_extension)) ||
+ !handler->write_formats)
+ return sox_false;
+ while ((e = enc_arg(sox_encoding_t))) {
+ if (e == encoding->encoding) {
+ sox_bool has_bits;
+ for (has_bits = sox_false; (s = enc_arg(unsigned)); has_bits = sox_true)
+ if (s == encoding->bits_per_sample)
+ return sox_true;
+ if (!has_bits && !encoding->bits_per_sample)
+ return sox_true;
+ break;
+ }
+ while (enc_arg(unsigned));
+ }
+ return sox_false;
+ #undef enc_arg
+}
+
+static void set_output_format(sox_format_t * ft)
+{
+ sox_encoding_t e;
+ unsigned i, s;
+ unsigned const * encodings = ft->handler.write_formats;
+#define enc_arg(T) (T)encodings[i++]
+
+ if (ft->handler.write_rates){
+ if (!ft->signal.rate)
+ ft->signal.rate = ft->handler.write_rates[0];
+ else {
+ sox_rate_t r;
+ i = 0;
+ while ((r = ft->handler.write_rates[i++])) {
+ if (r == ft->signal.rate)
+ break;
+ }
+ if (r != ft->signal.rate) {
+ sox_rate_t given = ft->signal.rate, max = 0;
+ ft->signal.rate = HUGE_VAL;
+ i = 0;
+ while ((r = ft->handler.write_rates[i++])) {
+ if (r > given && r < ft->signal.rate)
+ ft->signal.rate = r;
+ else max = max(r, max);
+ }
+ if (ft->signal.rate == HUGE_VAL)
+ ft->signal.rate = max;
+ lsx_warn("%s can't encode at %gHz; using %gHz", ft->handler.names[0], given, ft->signal.rate);
+ }
+ }
+ }
+ else if (!ft->signal.rate)
+ ft->signal.rate = SOX_DEFAULT_RATE;
+
+ if (ft->handler.flags & SOX_FILE_CHANS) {
+ if (ft->signal.channels == 1 && !(ft->handler.flags & SOX_FILE_MONO)) {
+ ft->signal.channels = (ft->handler.flags & SOX_FILE_STEREO)? 2 : 4;
+ lsx_warn("%s can't encode mono; setting channels to %u", ft->handler.names[0], ft->signal.channels);
+ } else
+ if (ft->signal.channels == 2 && !(ft->handler.flags & SOX_FILE_STEREO)) {
+ ft->signal.channels = (ft->handler.flags & SOX_FILE_QUAD)? 4 : 1;
+ lsx_warn("%s can't encode stereo; setting channels to %u", ft->handler.names[0], ft->signal.channels);
+ } else
+ if (ft->signal.channels == 4 && !(ft->handler.flags & SOX_FILE_QUAD)) {
+ ft->signal.channels = (ft->handler.flags & SOX_FILE_STEREO)? 2 : 1;
+ lsx_warn("%s can't encode quad; setting channels to %u", ft->handler.names[0], ft->signal.channels);
+ }
+ } else ft->signal.channels = max(ft->signal.channels, 1);
+
+ if (!encodings)
+ return;
+ /* If an encoding has been given, check if it supported by this handler */
+ if (ft->encoding.encoding) {
+ i = 0;
+ while ((e = enc_arg(sox_encoding_t))) {
+ if (e == ft->encoding.encoding)
+ break;
+ while (enc_arg(unsigned));
+ }
+ if (e != ft->encoding.encoding) {
+ lsx_warn("%s can't encode %s", ft->handler.names[0], sox_encodings_info[ft->encoding.encoding].desc);
+ ft->encoding.encoding = 0;
+ }
+ else {
+ unsigned max_p = 0;
+ unsigned max_p_s = 0;
+ unsigned given_size = 0;
+ sox_bool found = sox_false;
+ if (ft->encoding.bits_per_sample)
+ given_size = ft->encoding.bits_per_sample;
+ ft->encoding.bits_per_sample = 65;
+ while ((s = enc_arg(unsigned))) {
+ if (s == given_size)
+ found = sox_true;
+ if (sox_precision(e, s) >= ft->signal.precision) {
+ if (s < ft->encoding.bits_per_sample)
+ ft->encoding.bits_per_sample = s;
+ }
+ else if (sox_precision(e, s) > max_p) {
+ max_p = sox_precision(e, s);
+ max_p_s = s;
+ }
+ }
+ if (ft->encoding.bits_per_sample == 65)
+ ft->encoding.bits_per_sample = max_p_s;
+ if (given_size) {
+ if (found)
+ ft->encoding.bits_per_sample = given_size;
+ else lsx_warn("%s can't encode %s to %u-bit", ft->handler.names[0], sox_encodings_info[ft->encoding.encoding].desc, given_size);
+ }
+ }
+ }
+
+ /* If a size has been given, check if it supported by this handler */
+ if (!ft->encoding.encoding && ft->encoding.bits_per_sample) {
+ i = 0;
+ s= 0;
+ while (s != ft->encoding.bits_per_sample && (e = enc_arg(sox_encoding_t)))
+ while ((s = enc_arg(unsigned)) && s != ft->encoding.bits_per_sample);
+ if (s != ft->encoding.bits_per_sample) {
+ lsx_warn("%s can't encode to %u-bit", ft->handler.names[0], ft->encoding.bits_per_sample);
+ ft->encoding.bits_per_sample = 0;
+ }
+ else ft->encoding.encoding = e;
+ }
+
+ /* Find the smallest lossless encoding with precision >= signal.precision */
+ if (!ft->encoding.encoding) {
+ ft->encoding.bits_per_sample = 65;
+ i = 0;
+ while ((e = enc_arg(sox_encoding_t)))
+ while ((s = enc_arg(unsigned)))
+ if (!(sox_encodings_info[e].flags & (SOX_LOSSY1 | SOX_LOSSY2)) &&
+ sox_precision(e, s) >= ft->signal.precision && s < ft->encoding.bits_per_sample) {
+ ft->encoding.encoding = e;
+ ft->encoding.bits_per_sample = s;
+ }
+ }
+
+ /* Find the smallest lossy encoding with precision >= signal precision,
+ * or, if none such, the highest precision encoding */
+ if (!ft->encoding.encoding) {
+ unsigned max_p = 0;
+ sox_encoding_t max_p_e = 0;
+ unsigned max_p_s = 0;
+ i = 0;
+ while ((e = enc_arg(sox_encoding_t)))
+ do {
+ s = enc_arg(unsigned);
+ if (sox_precision(e, s) >= ft->signal.precision) {
+ if (s < ft->encoding.bits_per_sample) {
+ ft->encoding.encoding = e;
+ ft->encoding.bits_per_sample = s;
+ }
+ }
+ else if (sox_precision(e, s) > max_p) {
+ max_p = sox_precision(e, s);
+ max_p_e = e;
+ max_p_s = s;
+ }
+ } while (s);
+ if (!ft->encoding.encoding) {
+ ft->encoding.encoding = max_p_e;
+ ft->encoding.bits_per_sample = max_p_s;
+ }
+ }
+ ft->signal.precision = min(ft->signal.precision, sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample));
+ #undef enc_arg
+}
+
+sox_format_handler_t const * sox_write_handler(
+ char const * path,
+ char const * filetype,
+ char const * * filetype1)
+{
+ sox_format_handler_t const * handler;
+ if (filetype) {
+ if (!(handler = sox_find_format(filetype, sox_false))) {
+ if (filetype1)
+ lsx_fail("no handler for given file type `%s'", filetype);
+ return NULL;
+ }
+ }
+ else if (path) {
+ if (!(filetype = lsx_find_file_extension(path))) {
+ if (filetype1)
+ lsx_fail("can't determine type of `%s'", path);
+ return NULL;
+ }
+ if (!(handler = sox_find_format(filetype, sox_true))) {
+ if (filetype1)
+ lsx_fail("no handler for file extension `%s'", filetype);
+ return NULL;
+ }
+ }
+ else return NULL;
+ if (!handler->startwrite && !handler->write) {
+ if (filetype1)
+ lsx_fail("file type `%s' isn't writeable", filetype);
+ return NULL;
+ }
+ if (filetype1)
+ *filetype1 = filetype;
+ return handler;
+}
+
+static sox_format_t * open_write(
+ char const * path,
+ void * buffer UNUSED,
+ size_t buffer_size UNUSED,
+ char * * buffer_ptr UNUSED,
+ size_t * buffer_size_ptr UNUSED,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob,
+ sox_bool (*overwrite_permitted)(const char *filename))
+{
+ sox_format_t * ft = lsx_calloc(sizeof(*ft), 1);
+ sox_format_handler_t const * handler;
+
+ if (!path || !signal) {
+ lsx_fail("must specify file name and signal parameters to write file");
+ goto error;
+ }
+
+ if (!(handler = sox_write_handler(path, filetype, &filetype)))
+ goto error;
+
+ ft->handler = *handler;
+
+ if (!(ft->handler.flags & SOX_FILE_NOSTDIO)) {
+ if (!strcmp(path, "-")) { /* Use stdout if the filename is "-" */
+ if (sox_globals.stdout_in_use_by) {
+ lsx_fail("`-' (stdout) already in use by `%s'", sox_globals.stdout_in_use_by);
+ goto error;
+ }
+ sox_globals.stdout_in_use_by = "audio output";
+ SET_BINARY_MODE(stdout);
+ ft->fp = stdout;
+ }
+ else {
+ struct stat st;
+ if (!stat(path, &st) && (st.st_mode & S_IFMT) == S_IFREG &&
+ (overwrite_permitted && !overwrite_permitted(path))) {
+ lsx_fail("permission to overwrite `%s' denied", path);
+ goto error;
+ }
+ ft->fp =
+#ifdef HAVE_FMEMOPEN
+ buffer? fmemopen(buffer, buffer_size, "w+b") :
+ buffer_ptr? open_memstream(buffer_ptr, buffer_size_ptr) :
+#endif
+ fopen(path, "w+b");
+ if (ft->fp == NULL) {
+ lsx_fail("can't open output file `%s': %s", path, strerror(errno));
+ goto error;
+ }
+ }
+
+ /* stdout tends to be line-buffered. Override this */
+ /* to be Full Buffering. */
+ if (setvbuf (ft->fp, NULL, _IOFBF, sizeof(char) * sox_globals.bufsiz)) {
+ lsx_fail("Can't set write buffer");
+ goto error;
+ }
+ ft->seekable = is_seekable(ft);
+ }
+
+ ft->filetype = lsx_strdup(filetype);
+ ft->filename = lsx_strdup(path);
+ ft->mode = 'w';
+ ft->signal = *signal;
+
+ if (encoding)
+ ft->encoding = *encoding;
+ else sox_init_encodinginfo(&ft->encoding);
+ set_endiannesses(ft);
+
+ if (oob) {
+ ft->oob = *oob;
+ /* deep copy: */
+ ft->oob.comments = sox_copy_comments(oob->comments);
+ }
+
+ set_output_format(ft);
+
+ /* FIXME: doesn't cover the situation where
+ * codec changes audio length due to block alignment (e.g. 8svx, gsm): */
+ if (signal->rate && signal->channels)
+ ft->signal.length = ft->signal.length * ft->signal.rate / signal->rate *
+ ft->signal.channels / signal->channels + .5;
+
+ if ((ft->handler.flags & SOX_FILE_REWIND) && strcmp(ft->filetype, "sox") && !ft->signal.length && !ft->seekable)
+ lsx_warn("can't seek in output file `%s'; length in file header will be unspecified", ft->filename);
+
+ ft->priv = lsx_calloc(1, ft->handler.priv_size);
+ /* Read and write starters can change their formats. */
+ if (ft->handler.startwrite && (ft->handler.startwrite)(ft) != SOX_SUCCESS){
+ lsx_fail("can't open output file `%s': %s", ft->filename, ft->sox_errstr);
+ goto error;
+ }
+
+ if (sox_checkformat(ft) != SOX_SUCCESS) {
+ lsx_fail("bad format for output file `%s': %s", ft->filename, ft->sox_errstr);
+ goto error;
+ }
+
+ if ((ft->handler.flags & SOX_FILE_DEVICE) && signal) {
+ if (signal->rate && signal->rate != ft->signal.rate)
+ lsx_report("can't set sample rate %g; using %g", signal->rate, ft->signal.rate);
+ if (signal->channels && signal->channels != ft->signal.channels)
+ lsx_report("can't set %u channels; using %u", signal->channels, ft->signal.channels);
+ }
+ return ft;
+
+error:
+ if (ft->fp && ft->fp != stdout)
+ xfclose(ft->fp, ft->io_type);
+ free(ft->priv);
+ free(ft->filename);
+ free(ft->filetype);
+ free(ft);
+ return NULL;
+}
+
+sox_format_t * sox_open_write(
+ char const * path,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob,
+ sox_bool (*overwrite_permitted)(const char *filename))
+{
+ return open_write(path, NULL, (size_t)0, NULL, NULL, signal, encoding, filetype, oob, overwrite_permitted);
+}
+
+sox_format_t * sox_open_mem_write(
+ void * buffer,
+ size_t buffer_size,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob)
+{
+ return open_write("", buffer, buffer_size, NULL, NULL, signal, encoding, filetype, oob, NULL);
+}
+
+sox_format_t * sox_open_memstream_write(
+ char * * buffer_ptr,
+ size_t * buffer_size_ptr,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob)
+{
+ return open_write("", NULL, (size_t)0, buffer_ptr, buffer_size_ptr, signal, encoding, filetype, oob, NULL);
+}
+
+size_t sox_read(sox_format_t * ft, sox_sample_t * buf, size_t len)
+{
+ size_t actual;
+ if (ft->signal.length != SOX_UNSPEC)
+ len = min(len, ft->signal.length - ft->olength);
+ actual = ft->handler.read? (*ft->handler.read)(ft, buf, len) : 0;
+ actual = actual > len? 0 : actual;
+ ft->olength += actual;
+ return actual;
+}
+
+size_t sox_write(sox_format_t * ft, const sox_sample_t *buf, size_t len)
+{
+ size_t actual = ft->handler.write? (*ft->handler.write)(ft, buf, len) : 0;
+ ft->olength += actual;
+ return actual;
+}
+
+int sox_close(sox_format_t * ft)
+{
+ int result = SOX_SUCCESS;
+
+ if (ft->mode == 'r')
+ result = ft->handler.stopread? (*ft->handler.stopread)(ft) : SOX_SUCCESS;
+ else {
+ if (ft->handler.flags & SOX_FILE_REWIND) {
+ if (ft->olength != ft->signal.length && ft->seekable) {
+ result = lsx_seeki(ft, (off_t)0, 0);
+ if (result == SOX_SUCCESS)
+ result = ft->handler.stopwrite? (*ft->handler.stopwrite)(ft)
+ : ft->handler.startwrite?(*ft->handler.startwrite)(ft) : SOX_SUCCESS;
+ }
+ }
+ else result = ft->handler.stopwrite? (*ft->handler.stopwrite)(ft) : SOX_SUCCESS;
+ }
+
+ if (ft->fp && ft->fp != stdin && ft->fp != stdout)
+ xfclose(ft->fp, ft->io_type);
+ free(ft->priv);
+ free(ft->filename);
+ free(ft->filetype);
+ sox_delete_comments(&ft->oob.comments);
+
+ free(ft);
+ return result;
+}
+
+int sox_seek(sox_format_t * ft, uint64_t offset, int whence)
+{
+ /* FIXME: Implement SOX_SEEK_CUR and SOX_SEEK_END. */
+ if (whence != SOX_SEEK_SET)
+ return SOX_EOF; /* FIXME: return SOX_EINVAL */
+
+ /* If file is a seekable file and this handler supports seeking,
+ * then invoke handler's function.
+ */
+ if (ft->seekable && ft->handler.seek)
+ return (*ft->handler.seek)(ft, offset);
+ return SOX_EOF; /* FIXME: return SOX_EBADF */
+}
+
+static int strcaseends(char const * str, char const * end)
+{
+ size_t str_len = strlen(str), end_len = strlen(end);
+ return str_len >= end_len && !strcasecmp(str + str_len - end_len, end);
+}
+
+typedef enum {None, M3u, Pls} playlist_t;
+
+static playlist_t playlist_type(char const * filename)
+{
+ char * x, * p;
+ playlist_t result = None;
+
+ if (*filename == '|')
+ return result;
+ if (strcaseends(filename, ".m3u"))
+ return M3u;
+ if (strcaseends(filename, ".pls"))
+ return Pls;
+ x = lsx_strdup(filename);
+ p = strrchr(x, '?');
+ if (p) {
+ *p = '\0';
+ result = playlist_type(x);
+ }
+ free(x);
+ return result;
+}
+
+sox_bool sox_is_playlist(char const * filename)
+{
+ return playlist_type(filename) != None;
+}
+
+int sox_parse_playlist(sox_playlist_callback_t callback, void * p, char const * const listname)
+{
+ sox_bool const is_pls = playlist_type(listname) == Pls;
+ int const comment_char = "#;"[is_pls];
+ size_t text_length = 100;
+ char * text = lsx_malloc(text_length + 1);
+ char * dirname = lsx_strdup(listname);
+ char * slash_pos = LAST_SLASH(dirname);
+ lsx_io_type io_type;
+ FILE * file = xfopen(listname, "r", &io_type);
+ char * filename;
+ int c, result = SOX_SUCCESS;
+
+ if (!slash_pos)
+ *dirname = '\0';
+ else
+ *slash_pos = '\0';
+
+ if (file == NULL) {
+ lsx_fail("Can't open playlist file `%s': %s", listname, strerror(errno));
+ result = SOX_EOF;
+ }
+ else {
+ do {
+ size_t i = 0;
+ size_t begin = 0, end = 0;
+
+ while (isspace(c = getc(file)));
+ if (c == EOF)
+ break;
+ while (c != EOF && !strchr("\r\n", c) && c != comment_char) {
+ if (i == text_length)
+ text = lsx_realloc(text, (text_length <<= 1) + 1);
+ text[i++] = c;
+ if (!strchr(" \t\f", c))
+ end = i;
+ c = getc(file);
+ }
+ if (ferror(file))
+ break;
+ if (c == comment_char) {
+ do c = getc(file);
+ while (c != EOF && !strchr("\r\n", c));
+ if (ferror(file))
+ break;
+ }
+ text[end] = '\0';
+ if (is_pls) {
+ char dummy;
+ if (!strncasecmp(text, "file", (size_t) 4) && sscanf(text + 4, "%*u=%c", &dummy) == 1)
+ begin = strchr(text + 5, '=') - text + 1;
+ else end = 0;
+ }
+ if (begin != end) {
+ char const * id = text + begin;
+
+ if (!dirname[0] || is_url(id) || IS_ABSOLUTE(id))
+ filename = lsx_strdup(id);
+ else {
+ filename = lsx_malloc(strlen(dirname) + strlen(id) + 2);
+ sprintf(filename, "%s/%s", dirname, id);
+ }
+ if (sox_is_playlist(filename))
+ sox_parse_playlist(callback, p, filename);
+ else if (callback(p, filename))
+ c = EOF;
+ free(filename);
+ }
+ } while (c != EOF);
+
+ if (ferror(file)) {
+ lsx_fail("error reading playlist file `%s': %s", listname, strerror(errno));
+ result = SOX_EOF;
+ }
+ if (xfclose(file, io_type) && io_type == lsx_io_url) {
+ lsx_fail("error reading playlist file URL `%s'", listname);
+ result = SOX_EOF;
+ }
+ }
+ free(text);
+ free(dirname);
+ return result;
+}
+
+/*----------------------------- Formats library ------------------------------*/
+
+enum {
+ #define FORMAT(f) f,
+ #include "formats.h"
+ #undef FORMAT
+ NSTATIC_FORMATS
+};
+
+static sox_bool plugins_initted = sox_false;
+
+#ifdef HAVE_LIBLTDL /* Plugin format handlers */
+ #define MAX_DYNAMIC_FORMATS 42
+ #define MAX_FORMATS (NSTATIC_FORMATS + MAX_DYNAMIC_FORMATS)
+ #define MAX_FORMATS_1 (MAX_FORMATS + 1)
+ #define MAX_NAME_LEN (size_t)1024 /* FIXME: Use vasprintf */
+
+ static unsigned nformats = NSTATIC_FORMATS;
+
+ static int init_format(const char *file, lt_ptr data)
+ {
+ lt_dlhandle lth = lt_dlopenext(file);
+ const char *end = file + strlen(file);
+ const char prefix[] = "sox_fmt_";
+ char fnname[MAX_NAME_LEN];
+ char *start = strstr(file, prefix);
+
+ (void)data;
+ if (start && (start += sizeof(prefix) - 1) < end) {
+ int ret = snprintf(fnname, MAX_NAME_LEN,
+ "lsx_%.*s_format_fn", (int)(end - start), start);
+ if (ret > 0 && ret < (int)MAX_NAME_LEN) {
+ union {sox_format_fn_t fn; lt_ptr ptr;} ltptr;
+ ltptr.ptr = lt_dlsym(lth, fnname);
+ lsx_debug("opening format plugin `%s': library %p, entry point %p\n",
+ fnname, (void *)lth, ltptr.ptr);
+ if (ltptr.fn && (ltptr.fn()->sox_lib_version_code & ~255) ==
+ (SOX_LIB_VERSION_CODE & ~255)) { /* compatible version check */
+ if (nformats == MAX_FORMATS) {
+ lsx_warn("too many plugin formats");
+ return -1;
+ }
+ sox_format_fns[nformats++].fn = ltptr.fn;
+ }
+ }
+ }
+ return 0;
+ }
+#else
+ #define MAX_FORMATS_1
+#endif
+
+#define FORMAT(f) extern sox_format_handler_t const * lsx_##f##_format_fn(void);
+#include "formats.h"
+#undef FORMAT
+
+sox_format_tab_t sox_format_fns[MAX_FORMATS_1] = {
+ #define FORMAT(f) {NULL, lsx_##f##_format_fn},
+ #include "formats.h"
+ #undef FORMAT
+ {NULL, NULL}
+};
+
+int sox_format_init(void) /* Find & load format handlers. */
+{
+ if (plugins_initted)
+ return SOX_EOF;
+
+ plugins_initted = sox_true;
+#ifdef HAVE_LIBLTDL
+ {
+ int error = lt_dlinit();
+ if (error) {
+ lsx_fail("lt_dlinit failed with %d error(s): %s", error, lt_dlerror());
+ return SOX_EOF;
+ }
+ lt_dlforeachfile(PKGLIBDIR, init_format, NULL);
+ }
+#endif
+ return SOX_SUCCESS;
+}
+
+void sox_format_quit(void) /* Cleanup things. */
+{
+#ifdef HAVE_LIBLTDL
+ int ret;
+ if (plugins_initted && (ret = lt_dlexit()) != 0)
+ lsx_fail("lt_dlexit failed with %d error(s): %s", ret, lt_dlerror());
+#endif
+}
+
+/* Find a named format in the formats library.
+ *
+ * (c) 2005-9 Chris Bagwell and SoX contributors.
+ * Copyright 1991 Lance Norskog And Sundry Contributors.
+ *
+ * This source code is freely redistributable and may be used for any
+ * purpose. This copyright notice must be maintained.
+ *
+ * Lance Norskog, Sundry Contributors, Chris Bagwell and SoX contributors
+ * are not responsible for the consequences of using this software.
+ */
+sox_format_handler_t const * sox_find_format(char const * name0, sox_bool no_dev)
+{
+ size_t f, n;
+
+ if (name0) {
+ char * name = lsx_strdup(name0);
+ char * pos = strchr(name, ';');
+ if (pos) /* Use only the 1st clause of a mime string */
+ *pos = '\0';
+ for (f = 0; sox_format_fns[f].fn; ++f) {
+ sox_format_handler_t const * handler = sox_format_fns[f].fn();
+
+ if (!(no_dev && (handler->flags & SOX_FILE_DEVICE)))
+ for (n = 0; handler->names[n]; ++n)
+ if (!strcasecmp(handler->names[n], name)) {
+ free(name);
+ return handler; /* Found it. */
+ }
+ }
+ free(name);
+ }
+ if (sox_format_init() == SOX_SUCCESS) /* Try again with plugins */
+ return sox_find_format(name0, no_dev);
+ return NULL;
+}
diff --git a/util/sox/src/formats.h b/util/sox/src/formats.h
new file mode 100644
index 00000000..78149ca4
--- /dev/null
+++ b/util/sox/src/formats.h
@@ -0,0 +1,131 @@
+/* libSoX static formats list (c) 2006-9 Chris Bagwell and SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*-------------------------- Static format handlers --------------------------*/
+
+ FORMAT(aifc)
+ FORMAT(aiff)
+ FORMAT(al)
+ FORMAT(au)
+ FORMAT(avr)
+ FORMAT(cdr)
+ FORMAT(cvsd)
+ FORMAT(cvu)
+ FORMAT(dat)
+ FORMAT(dvms)
+ FORMAT(f4)
+ FORMAT(f8)
+ FORMAT(gsrt)
+ FORMAT(hcom)
+ FORMAT(htk)
+ FORMAT(ima)
+ FORMAT(la)
+ FORMAT(lu)
+ FORMAT(maud)
+ FORMAT(nul)
+ FORMAT(prc)
+ FORMAT(raw)
+ FORMAT(s1)
+ FORMAT(s2)
+ FORMAT(s3)
+ FORMAT(s4)
+ FORMAT(sf)
+ FORMAT(smp)
+ FORMAT(sounder)
+ FORMAT(soundtool)
+ FORMAT(sox)
+ FORMAT(sphere)
+ FORMAT(svx)
+ FORMAT(txw)
+ FORMAT(u1)
+ FORMAT(u2)
+ FORMAT(u3)
+ FORMAT(u4)
+ FORMAT(ul)
+ FORMAT(voc)
+ FORMAT(vox)
+ FORMAT(wav)
+ FORMAT(wve)
+ FORMAT(xa)
+
+/*--------------------- Plugin or static format handlers ---------------------*/
+
+#if defined HAVE_ALSA && (defined STATIC_ALSA || !defined HAVE_LIBLTDL)
+ FORMAT(alsa)
+#endif
+#if defined HAVE_AMRNB && (defined STATIC_AMRNB || !defined HAVE_LIBLTDL)
+ FORMAT(amr_nb)
+#endif
+#if defined HAVE_AMRWB && (defined STATIC_AMRWB || !defined HAVE_LIBLTDL)
+ FORMAT(amr_wb)
+#endif
+#if defined HAVE_AO && (defined STATIC_AO || !defined HAVE_LIBLTDL)
+ FORMAT(ao)
+#endif
+#if defined HAVE_COREAUDIO && (defined STATIC_COREAUDIO || !defined HAVE_LIBLTDL)
+ FORMAT(coreaudio)
+#endif
+#if defined HAVE_FFMPEG && (defined STATIC_FFMPEG || !defined HAVE_LIBLTDL)
+ FORMAT(ffmpeg)
+#endif
+#if defined HAVE_FLAC && (defined STATIC_FLAC || !defined HAVE_LIBLTDL)
+ FORMAT(flac)
+#endif
+#if defined HAVE_GSM && (defined STATIC_GSM || !defined HAVE_LIBLTDL)
+ FORMAT(gsm)
+#endif
+#if defined HAVE_LPC10 && (defined STATIC_LPC10 || !defined HAVE_LIBLTDL)
+ FORMAT(lpc10)
+#endif
+#if defined HAVE_MP3 && (defined STATIC_MP3 || !defined HAVE_LIBLTDL)
+ FORMAT(mp3)
+#endif
+#if defined HAVE_OSS && (defined STATIC_OSS || !defined HAVE_LIBLTDL)
+ FORMAT(oss)
+#endif
+#if defined HAVE_PULSEAUDIO && (defined STATIC_PULSEAUDIO || !defined HAVE_LIBLTDL)
+ FORMAT(pulseaudio)
+#endif
+#if defined HAVE_WAVEAUDIO && (defined STATIC_WAVEAUDIO || !defined HAVE_LIBLTDL)
+ FORMAT(waveaudio)
+#endif
+#if defined HAVE_SNDIO && (defined STATIC_SNDIO || !defined HAVE_LIBLTDL)
+ FORMAT(sndio)
+#endif
+#if defined HAVE_SNDFILE && (defined STATIC_SNDFILE || !defined HAVE_LIBLTDL)
+ FORMAT(sndfile)
+ #if defined HAVE_SNDFILE_1_0_12
+ FORMAT(caf)
+ #endif
+ FORMAT(fap)
+ FORMAT(mat4)
+ FORMAT(mat5)
+ FORMAT(paf)
+ FORMAT(pvf)
+ FORMAT(sd2)
+ FORMAT(w64)
+ FORMAT(xi)
+#endif
+#if defined HAVE_SUN_AUDIO && (defined STATIC_SUN_AUDIO || !defined HAVE_LIBLTDL)
+ FORMAT(sunau)
+#endif
+#if defined HAVE_OGG_VORBIS && (defined STATIC_OGG_VORBIS || !defined HAVE_LIBLTDL)
+ FORMAT(vorbis)
+#endif
+#if defined HAVE_WAVPACK && (defined STATIC_WAVPACK || !defined HAVE_LIBLTDL)
+ FORMAT(wavpack)
+#endif
diff --git a/util/sox/src/sox.h b/util/sox/src/sox.h
new file mode 100644
index 00000000..4e7b1647
--- /dev/null
+++ b/util/sox/src/sox.h
@@ -0,0 +1,614 @@
+/* libSoX Library Public Interface
+ *
+ * Copyright 1999-2009 Chris Bagwell and SoX Contributors.
+ *
+ * This source code is freely redistributable and may be used for
+ * any purpose. This copyright notice must be maintained.
+ * Chris Bagwell And SoX Contributors are not responsible for
+ * the consequences of using this software.
+ */
+
+#ifndef SOX_H
+#define SOX_H
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h> /* Ensure NULL etc. are available throughout SoX */
+#include <stdio.h>
+#include <stdlib.h>
+#include "soxstdint.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Avoid warnings about unused parameters. */
+#ifdef __GNUC__
+#define UNUSED __attribute__ ((unused))
+#define PRINTF __attribute__ ((format (printf, 1, 2)))
+#else
+#define UNUSED
+#define PRINTF
+#endif
+#ifdef _MSC_VER
+#define LSX_UNUSED_VAR(x) ((void)(x))
+#else
+#define LSX_UNUSED_VAR(x) ((void)0)
+#endif
+
+/* The following is the API version of libSoX. It is not meant
+ * to follow the version number of SoX but it has historically.
+ * Please do not count on these numbers being in sync.
+ */
+#define SOX_LIB_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define SOX_LIB_VERSION_CODE SOX_LIB_VERSION(14, 3, 2)
+
+const char *sox_version(void); /* Returns version number */
+
+#define SOX_SUCCESS 0
+#define SOX_EOF (-1) /* End Of File or other error */
+
+enum { /* libSoX specific error codes. The rest directly map from errno. */
+ SOX_EHDR = 2000, /* Invalid Audio Header */
+ SOX_EFMT, /* Unsupported data format */
+ SOX_ENOMEM, /* Can't alloc memory */
+ SOX_EPERM, /* Operation not permitted */
+ SOX_ENOTSUP, /* Operation not supported */
+ SOX_EINVAL /* Invalid argument */
+};
+
+/* Boolean type, assignment (but not necessarily binary) compatible with
+ * C++ bool */
+typedef enum {sox_false, sox_true} sox_bool;
+
+typedef int32_t int24_t; /* But beware of the extra byte. */
+typedef uint32_t uint24_t; /* ditto */
+
+#define SOX_INT_MIN(bits) (1 <<((bits)-1))
+#define SOX_INT_MAX(bits) (((unsigned)-1)>>(33-(bits)))
+#define SOX_UINT_MAX(bits) (SOX_INT_MIN(bits)|SOX_INT_MAX(bits))
+
+#define SOX_INT8_MAX SOX_INT_MAX(8)
+#define SOX_INT16_MAX SOX_INT_MAX(16)
+#define SOX_INT24_MAX SOX_INT_MAX(24)
+#define SOX_INT32_MAX SOX_INT_MAX(32)
+
+typedef int32_t sox_sample_t;
+
+/* Minimum and maximum values a sample can hold. */
+#define SOX_SAMPLE_PRECISION 32
+#define SOX_SAMPLE_MAX (sox_sample_t)SOX_INT_MAX(32)
+#define SOX_SAMPLE_MIN (sox_sample_t)SOX_INT_MIN(32)
+
+
+
+/* Conversions: Linear PCM <--> sox_sample_t
+ *
+ * I/O Input sox_sample_t Clips? Input sox_sample_t Clips?
+ * Format Minimum Minimum I O Maximum Maximum I O
+ * ------ --------- ------------ -- -- -------- ------------ -- --
+ * Float -inf -1 y n inf 1 - 5e-10 y n
+ * Int8 -128 -128 n n 127 127.9999999 n y
+ * Int16 -32768 -32768 n n 32767 32767.99998 n y
+ * Int24 -8388608 -8388608 n n 8388607 8388607.996 n y
+ * Int32 -2147483648 -2147483648 n n 2147483647 2147483647 n n
+ *
+ * Conversions are as accurate as possible (with rounding).
+ *
+ * Rounding: halves toward +inf, all others to nearest integer.
+ *
+ * Clips? shows whether on not there is the possibility of a conversion
+ * clipping to the minimum or maximum value when inputing from or outputing
+ * to a given type.
+ *
+ * Unsigned integers are converted to and from signed integers by flipping
+ * the upper-most bit then treating them as signed integers.
+ */
+
+#define SOX_SAMPLE_LOCALS sox_sample_t sox_macro_temp_sample UNUSED; \
+ double sox_macro_temp_double UNUSED
+
+#define SOX_SAMPLE_NEG SOX_INT_MIN(32)
+#define SOX_SAMPLE_TO_UNSIGNED(bits,d,clips) \
+ (uint##bits##_t)(SOX_SAMPLE_TO_SIGNED(bits,d,clips)^SOX_INT_MIN(bits))
+#define SOX_SAMPLE_TO_SIGNED(bits,d,clips) \
+ (int##bits##_t)(LSX_UNUSED_VAR(sox_macro_temp_double),sox_macro_temp_sample=(d),sox_macro_temp_sample>SOX_SAMPLE_MAX-(1<<(31-bits))?++(clips),SOX_INT_MAX(bits):((uint32_t)(sox_macro_temp_sample+(1<<(31-bits))))>>(32-bits))
+#define SOX_SIGNED_TO_SAMPLE(bits,d)((sox_sample_t)(d)<<(32-bits))
+#define SOX_UNSIGNED_TO_SAMPLE(bits,d)(SOX_SIGNED_TO_SAMPLE(bits,d)^SOX_SAMPLE_NEG)
+
+#define SOX_UNSIGNED_8BIT_TO_SAMPLE(d,clips) SOX_UNSIGNED_TO_SAMPLE(8,d)
+#define SOX_SIGNED_8BIT_TO_SAMPLE(d,clips) SOX_SIGNED_TO_SAMPLE(8,d)
+#define SOX_UNSIGNED_16BIT_TO_SAMPLE(d,clips) SOX_UNSIGNED_TO_SAMPLE(16,d)
+#define SOX_SIGNED_16BIT_TO_SAMPLE(d,clips) SOX_SIGNED_TO_SAMPLE(16,d)
+#define SOX_UNSIGNED_24BIT_TO_SAMPLE(d,clips) SOX_UNSIGNED_TO_SAMPLE(24,d)
+#define SOX_SIGNED_24BIT_TO_SAMPLE(d,clips) SOX_SIGNED_TO_SAMPLE(24,d)
+#define SOX_UNSIGNED_32BIT_TO_SAMPLE(d,clips) ((sox_sample_t)(d)^SOX_SAMPLE_NEG)
+#define SOX_SIGNED_32BIT_TO_SAMPLE(d,clips) (sox_sample_t)(d)
+#define SOX_FLOAT_32BIT_TO_SAMPLE(d,clips) (sox_sample_t)(LSX_UNUSED_VAR(sox_macro_temp_sample),sox_macro_temp_double=(d)*(SOX_SAMPLE_MAX+1.),sox_macro_temp_double<SOX_SAMPLE_MIN?++(clips),SOX_SAMPLE_MIN:sox_macro_temp_double>=SOX_SAMPLE_MAX+1.?sox_macro_temp_double>SOX_SAMPLE_MAX+1.?++(clips),SOX_SAMPLE_MAX:SOX_SAMPLE_MAX:sox_macro_temp_double)
+#define SOX_FLOAT_64BIT_TO_SAMPLE(d,clips) (sox_sample_t)(LSX_UNUSED_VAR(sox_macro_temp_sample),sox_macro_temp_double=(d)*(SOX_SAMPLE_MAX+1.),sox_macro_temp_double<0?sox_macro_temp_double<=SOX_SAMPLE_MIN-.5?++(clips),SOX_SAMPLE_MIN:sox_macro_temp_double-.5:sox_macro_temp_double>=SOX_SAMPLE_MAX+.5?sox_macro_temp_double>SOX_SAMPLE_MAX+1.?++(clips),SOX_SAMPLE_MAX:SOX_SAMPLE_MAX:sox_macro_temp_double+.5)
+#define SOX_SAMPLE_TO_UNSIGNED_8BIT(d,clips) SOX_SAMPLE_TO_UNSIGNED(8,d,clips)
+#define SOX_SAMPLE_TO_SIGNED_8BIT(d,clips) SOX_SAMPLE_TO_SIGNED(8,d,clips)
+#define SOX_SAMPLE_TO_UNSIGNED_16BIT(d,clips) SOX_SAMPLE_TO_UNSIGNED(16,d,clips)
+#define SOX_SAMPLE_TO_SIGNED_16BIT(d,clips) SOX_SAMPLE_TO_SIGNED(16,d,clips)
+#define SOX_SAMPLE_TO_UNSIGNED_24BIT(d,clips) SOX_SAMPLE_TO_UNSIGNED(24,d,clips)
+#define SOX_SAMPLE_TO_SIGNED_24BIT(d,clips) SOX_SAMPLE_TO_SIGNED(24,d,clips)
+#define SOX_SAMPLE_TO_UNSIGNED_32BIT(d,clips) (uint32_t)((d)^SOX_SAMPLE_NEG)
+#define SOX_SAMPLE_TO_SIGNED_32BIT(d,clips) (int32_t)(d)
+#define SOX_SAMPLE_TO_FLOAT_32BIT(d,clips) (LSX_UNUSED_VAR(sox_macro_temp_double),sox_macro_temp_sample=(d),sox_macro_temp_sample>SOX_SAMPLE_MAX-128?++(clips),1:(((sox_macro_temp_sample+128)&~255)*(1./(SOX_SAMPLE_MAX+1.))))
+#define SOX_SAMPLE_TO_FLOAT_64BIT(d,clips) ((d)*(1./(SOX_SAMPLE_MAX+1.)))
+
+
+
+/* MACRO to clip a data type that is greater then sox_sample_t to
+ * sox_sample_t's limits and increment a counter if clipping occurs..
+ */
+#define SOX_SAMPLE_CLIP_COUNT(samp, clips) \
+ do { \
+ if (samp > SOX_SAMPLE_MAX) \
+ { samp = SOX_SAMPLE_MAX; clips++; } \
+ else if (samp < SOX_SAMPLE_MIN) \
+ { samp = SOX_SAMPLE_MIN; clips++; } \
+ } while (0)
+
+/* Rvalue MACRO to round and clip a double to a sox_sample_t,
+ * and increment a counter if clipping occurs.
+ */
+#define SOX_ROUND_CLIP_COUNT(d, clips) \
+ ((d) < 0? (d) <= SOX_SAMPLE_MIN - 0.5? ++(clips), SOX_SAMPLE_MIN: (d) - 0.5 \
+ : (d) >= SOX_SAMPLE_MAX + 0.5? ++(clips), SOX_SAMPLE_MAX: (d) + 0.5)
+
+/* Rvalue MACRO to clip an integer to a given number of bits
+ * and increment a counter if clipping occurs.
+ */
+#define SOX_INTEGER_CLIP_COUNT(bits,i,clips) ( \
+ (i) >(1 << ((bits)-1))- 1? ++(clips),(1 << ((bits)-1))- 1 : \
+ (i) <-1 << ((bits)-1) ? ++(clips),-1 << ((bits)-1) : (i))
+#define SOX_16BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(16,i,clips)
+#define SOX_24BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(24,i,clips)
+
+
+
+#define SOX_SIZE_MAX ((size_t)(-1))
+
+typedef void (*sox_output_message_handler_t)(unsigned level, const char *filename, const char *fmt, va_list ap);
+
+typedef struct { /* Global parameters (for effects & formats) */
+/* public: */
+ unsigned verbosity;
+ sox_output_message_handler_t output_message_handler;
+ sox_bool repeatable;
+/* The following is used at times in libSoX when alloc()ing buffers
+ * to perform file I/O. It can be useful to pass in similar sized
+ * data to get max performance.
+ */
+ size_t bufsiz, input_bufsiz;
+ int32_t ranqd1; /* Can be used to re-seed libSoX's PRNG */
+
+/* private: */
+ char const * stdin_in_use_by;
+ char const * stdout_in_use_by;
+ char const * subsystem;
+ char * tmp_path;
+ sox_bool use_magic;
+} sox_globals_t;
+extern sox_globals_t sox_globals;
+
+typedef double sox_rate_t;
+
+#define SOX_UNSPEC 0
+#define SOX_IGNORE_LENGTH (size_t)(-1)
+typedef struct { /* Signal parameters; SOX_UNSPEC if unknown */
+ sox_rate_t rate; /* sampling rate */
+ unsigned channels; /* number of sound channels */
+ unsigned precision; /* in bits */
+ size_t length; /* samples * chans in file */
+ double * mult; /* Effects headroom multiplier; may be null */
+} sox_signalinfo_t;
+
+typedef enum {
+ SOX_ENCODING_UNKNOWN ,
+
+ SOX_ENCODING_SIGN2 , /* signed linear 2's comp: Mac */
+ SOX_ENCODING_UNSIGNED , /* unsigned linear: Sound Blaster */
+ SOX_ENCODING_FLOAT , /* floating point (binary format) */
+ SOX_ENCODING_FLOAT_TEXT, /* floating point (text format) */
+ SOX_ENCODING_FLAC , /* FLAC compression */
+ SOX_ENCODING_HCOM , /* */
+ SOX_ENCODING_WAVPACK , /* */
+ SOX_ENCODING_WAVPACKF , /* */
+ SOX_ENCODING_ULAW , /* u-law signed logs: US telephony, SPARC */
+ SOX_ENCODING_ALAW , /* A-law signed logs: non-US telephony, Psion */
+ SOX_ENCODING_G721 , /* G.721 4-bit ADPCM */
+ SOX_ENCODING_G723 , /* G.723 3 or 5 bit ADPCM */
+ SOX_ENCODING_CL_ADPCM , /* Creative Labs 8 --> 2,3,4 bit Compressed PCM */
+ SOX_ENCODING_CL_ADPCM16, /* Creative Labs 16 --> 4 bit Compressed PCM */
+ SOX_ENCODING_MS_ADPCM , /* Microsoft Compressed PCM */
+ SOX_ENCODING_IMA_ADPCM , /* IMA Compressed PCM */
+ SOX_ENCODING_OKI_ADPCM , /* Dialogic/OKI Compressed PCM */
+ SOX_ENCODING_DPCM , /* */
+ SOX_ENCODING_DWVW , /* */
+ SOX_ENCODING_DWVWN , /* */
+ SOX_ENCODING_GSM , /* GSM 6.10 33byte frame lossy compression */
+ SOX_ENCODING_MP3 , /* MP3 compression */
+ SOX_ENCODING_VORBIS , /* Vorbis compression */
+ SOX_ENCODING_AMR_WB , /* AMR-WB compression */
+ SOX_ENCODING_AMR_NB , /* AMR-NB compression */
+ SOX_ENCODING_CVSD , /* */
+ SOX_ENCODING_LPC10 , /* */
+
+ SOX_ENCODINGS /* End of list marker */
+} sox_encoding_t;
+
+typedef struct {
+ unsigned flags;
+ #define SOX_LOSSY1 1 /* encode, decode, encode, decode: lossy once */
+ #define SOX_LOSSY2 2 /* encode, decode, encode, decode: lossy twice */
+
+ char const * name;
+ char const * desc;
+} sox_encodings_info_t;
+
+extern sox_encodings_info_t const sox_encodings_info[];
+
+typedef enum {SOX_OPTION_NO, SOX_OPTION_YES, SOX_OPTION_DEFAULT} sox_option_t;
+
+typedef struct { /* Encoding parameters */
+ sox_encoding_t encoding; /* format of sample numbers */
+ unsigned bits_per_sample; /* 0 if unknown or variable; uncompressed value if lossless; compressed value if lossy */
+ double compression; /* compression factor (where applicable) */
+
+ /* If these 3 variables are set to DEFAULT, then, during
+ * sox_open_read or sox_open_write, libSoX will set them to either
+ * NO or YES according to the machine or format default. */
+ sox_option_t reverse_bytes; /* endiannesses... */
+ sox_option_t reverse_nibbles;
+ sox_option_t reverse_bits;
+
+ sox_bool opposite_endian;
+} sox_encodinginfo_t;
+
+void sox_init_encodinginfo(sox_encodinginfo_t * e);
+unsigned sox_precision(sox_encoding_t encoding, unsigned pcm_size);
+
+/* Defaults for common hardware */
+#define SOX_DEFAULT_CHANNELS 2
+#define SOX_DEFAULT_RATE 48000
+#define SOX_DEFAULT_PRECISION 16
+#define SOX_DEFAULT_ENCODING SOX_ENCODING_SIGN2
+
+/* Loop parameters */
+
+typedef struct {
+ size_t start; /* first sample */
+ size_t length; /* length */
+ unsigned int count; /* number of repeats, 0=forever */
+ unsigned char type; /* 0=no, 1=forward, 2=forward/back */
+} sox_loopinfo_t;
+
+/* Instrument parameters */
+
+/* vague attempt at generic information for sampler-specific info */
+
+typedef struct {
+ int8_t MIDInote; /* for unity pitch playback */
+ int8_t MIDIlow, MIDIhi;/* MIDI pitch-bend range */
+ char loopmode; /* semantics of loop data */
+ unsigned nloops; /* number of active loops (max SOX_MAX_NLOOPS) */
+} sox_instrinfo_t;
+
+/* Loop modes, upper 4 bits mask the loop blass, lower 4 bits describe */
+/* the loop behaviour, ie. single shot, bidirectional etc. */
+#define SOX_LOOP_NONE 0
+#define SOX_LOOP_8 32 /* 8 loops: don't know ?? */
+#define SOX_LOOP_SUSTAIN_DECAY 64 /* AIFF style: one sustain & one decay loop */
+
+/*
+ * File buffer info. Holds info so that data can be read in blocks.
+ */
+
+typedef struct {
+ char *buf; /* Pointer to data buffer */
+ size_t size; /* Size of buffer */
+ size_t count; /* Count read in to buffer */
+ size_t pos; /* Position in buffer */
+} sox_fileinfo_t;
+
+
+/*
+ * Handler structure for each format.
+ */
+
+typedef struct sox_format sox_format_t;
+
+typedef struct {
+ unsigned sox_lib_version_code; /* Checked on load; must be 1st in struct*/
+ char const * description;
+ char const * const * names;
+ unsigned int flags;
+ int (*startread)(sox_format_t * ft);
+ size_t (*read)(sox_format_t * ft, sox_sample_t *buf, size_t len);
+ int (*stopread)(sox_format_t * ft);
+ int (*startwrite)(sox_format_t * ft);
+ size_t (*write)(sox_format_t * ft, const sox_sample_t *buf, size_t len);
+ int (*stopwrite)(sox_format_t * ft);
+ int (*seek)(sox_format_t * ft, uint64_t offset);
+ unsigned const * write_formats;
+ sox_rate_t const * write_rates;
+ size_t priv_size;
+} sox_format_handler_t;
+
+/*
+ * Format information for input and output files.
+ */
+
+typedef char * * sox_comments_t;
+
+size_t sox_num_comments(sox_comments_t comments);
+void sox_append_comment(sox_comments_t * comments, char const * comment);
+void sox_append_comments(sox_comments_t * comments, char const * comment);
+sox_comments_t sox_copy_comments(sox_comments_t comments);
+void sox_delete_comments(sox_comments_t * comments);
+char const * sox_find_comment(sox_comments_t comments, char const * id);
+
+#define SOX_MAX_NLOOPS 8
+
+typedef struct {
+ /* Decoded: */
+ sox_comments_t comments; /* Comment strings */
+ sox_instrinfo_t instr; /* Instrument specification */
+ sox_loopinfo_t loops[SOX_MAX_NLOOPS]; /* Looping specification */
+
+ /* TBD: Non-decoded chunks, etc: */
+} sox_oob_t; /* Out Of Band data */
+
+typedef enum {lsx_io_file, lsx_io_pipe, lsx_io_url} lsx_io_type;
+
+struct sox_format {
+ char * filename; /* File name */
+ sox_signalinfo_t signal; /* Signal specifications */
+ sox_encodinginfo_t encoding; /* Encoding specifications */
+ char * filetype; /* Type of file */
+ sox_oob_t oob; /* Out Of Band data */
+ sox_bool seekable; /* Can seek on this file */
+ char mode; /* Read or write mode ('r' or 'w') */
+ size_t olength; /* Samples * chans written to file */
+ size_t clips; /* Incremented if clipping occurs */
+ int sox_errno; /* Failure error code */
+ char sox_errstr[256]; /* Failure error text */
+ FILE * fp; /* File stream pointer */
+ lsx_io_type io_type;
+ long tell_off;
+ long data_start;
+ sox_format_handler_t handler; /* Format handler for this file */
+ void * priv; /* Format handler's private data area */
+};
+
+/* File flags field */
+#define SOX_FILE_NOSTDIO 0x0001 /* Does not use stdio routines */
+#define SOX_FILE_DEVICE 0x0002 /* File is an audio device */
+#define SOX_FILE_PHONY 0x0004 /* Phony file/device */
+#define SOX_FILE_REWIND 0x0008 /* File should be rewound to write header */
+#define SOX_FILE_BIT_REV 0x0010 /* Is file bit-reversed? */
+#define SOX_FILE_NIB_REV 0x0020 /* Is file nibble-reversed? */
+#define SOX_FILE_ENDIAN 0x0040 /* Is file format endian? */
+#define SOX_FILE_ENDBIG 0x0080 /* If so, is it big endian? */
+#define SOX_FILE_MONO 0x0100 /* Do channel restrictions allow mono? */
+#define SOX_FILE_STEREO 0x0200 /* Do channel restrictions allow stereo? */
+#define SOX_FILE_QUAD 0x0400 /* Do channel restrictions allow quad? */
+
+#define SOX_FILE_CHANS (SOX_FILE_MONO | SOX_FILE_STEREO | SOX_FILE_QUAD)
+#define SOX_FILE_LIT_END (SOX_FILE_ENDIAN | 0)
+#define SOX_FILE_BIG_END (SOX_FILE_ENDIAN | SOX_FILE_ENDBIG)
+
+int sox_format_init(void);
+void sox_format_quit(void);
+
+int sox_init(void);
+int sox_quit(void);
+
+typedef const sox_format_handler_t *(*sox_format_fn_t)(void);
+
+typedef struct {
+ char *name;
+ sox_format_fn_t fn;
+} sox_format_tab_t;
+
+extern sox_format_tab_t sox_format_fns[];
+
+sox_format_t * sox_open_read(
+ char const * path,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype);
+sox_format_t * sox_open_mem_read(
+ void * buffer,
+ size_t buffer_size,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype);
+sox_bool sox_format_supports_encoding(
+ char const * path,
+ char const * filetype,
+ sox_encodinginfo_t const * encoding);
+sox_format_handler_t const * sox_write_handler(
+ char const * path,
+ char const * filetype,
+ char const * * filetype1);
+sox_format_t * sox_open_write(
+ char const * path,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob,
+ sox_bool (*overwrite_permitted)(const char *filename));
+sox_format_t * sox_open_mem_write(
+ void * buffer,
+ size_t buffer_size,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob);
+sox_format_t * sox_open_memstream_write(
+ char * * buffer_ptr,
+ size_t * buffer_size_ptr,
+ sox_signalinfo_t const * signal,
+ sox_encodinginfo_t const * encoding,
+ char const * filetype,
+ sox_oob_t const * oob);
+size_t sox_read(sox_format_t * ft, sox_sample_t *buf, size_t len);
+size_t sox_write(sox_format_t * ft, const sox_sample_t *buf, size_t len);
+int sox_close(sox_format_t * ft);
+
+#define SOX_SEEK_SET 0
+int sox_seek(sox_format_t * ft, uint64_t offset, int whence);
+
+sox_format_handler_t const * sox_find_format(char const * name, sox_bool no_dev);
+
+/*
+ * Structures for effects.
+ */
+
+#define SOX_MAX_EFFECTS 20
+
+#define SOX_EFF_CHAN 1 /* Can alter # of channels */
+#define SOX_EFF_RATE 2 /* Can alter sample rate */
+#define SOX_EFF_PREC 4 /* Can alter sample precision */
+#define SOX_EFF_LENGTH 8 /* Can alter audio length */
+#define SOX_EFF_MCHAN 16 /* Can handle multi-channel */
+#define SOX_EFF_NULL 32 /* Does nothing */
+#define SOX_EFF_DEPRECATED 64 /* Is living on borrowed time */
+#define SOX_EFF_GAIN 128 /* Does not support gain -r */
+#define SOX_EFF_MODIFY 256 /* Does not modify samples */
+#define SOX_EFF_ALPHA 512 /* Is experimental/incomplete */
+#define SOX_EFF_INTERNAL 1024 /* Is in libSoX but not sox */
+
+typedef enum {sox_plot_off, sox_plot_octave, sox_plot_gnuplot, sox_plot_data} sox_plot_t;
+typedef struct sox_effect sox_effect_t;
+struct sox_effects_globals { /* Global parameters (for effects) */
+ sox_plot_t plot; /* To help the user choose effect & options */
+ sox_globals_t * global_info;
+};
+typedef struct sox_effects_globals sox_effects_globals_t;
+extern sox_effects_globals_t sox_effects_globals;
+
+typedef struct {
+ char const * name;
+ char const * usage;
+ unsigned int flags;
+
+ int (*getopts)(sox_effect_t * effp, int argc, char *argv[]);
+ int (*start)(sox_effect_t * effp);
+ int (*flow)(sox_effect_t * effp, const sox_sample_t *ibuf,
+ sox_sample_t *obuf, size_t *isamp, size_t *osamp);
+ int (*drain)(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp);
+ int (*stop)(sox_effect_t * effp);
+ int (*kill)(sox_effect_t * effp);
+ size_t priv_size;
+} sox_effect_handler_t;
+
+struct sox_effect {
+ sox_effects_globals_t * global_info; /* global parameters */
+ sox_signalinfo_t in_signal;
+ sox_signalinfo_t out_signal;
+ sox_encodinginfo_t const * in_encoding;
+ sox_encodinginfo_t const * out_encoding;
+ sox_effect_handler_t handler;
+ sox_sample_t * obuf; /* output buffer */
+ size_t obeg, oend; /* consumed, total length */
+ size_t imin; /* minimum input buffer size */
+ size_t clips; /* increment if clipping occurs */
+ size_t flows; /* 1 if MCHAN, # chans otherwise */
+ size_t flow; /* flow # */
+ void * priv; /* Effect's private data area */
+};
+
+sox_effect_handler_t const * sox_find_effect(char const * name);
+sox_effect_t * sox_create_effect(sox_effect_handler_t const * eh);
+int sox_effect_options(sox_effect_t *effp, int argc, char * const argv[]);
+
+/* Effects chain */
+
+typedef const sox_effect_handler_t *(*sox_effect_fn_t)(void);
+extern sox_effect_fn_t sox_effect_fns[];
+
+struct sox_effects_chain {
+ sox_effect_t * effects[SOX_MAX_EFFECTS];
+ unsigned length;
+ sox_sample_t **ibufc, **obufc; /* Channel interleave buffers */
+ sox_effects_globals_t global_info;
+ sox_encodinginfo_t const * in_enc;
+ sox_encodinginfo_t const * out_enc;
+};
+typedef struct sox_effects_chain sox_effects_chain_t;
+sox_effects_chain_t * sox_create_effects_chain(
+ sox_encodinginfo_t const * in_enc, sox_encodinginfo_t const * out_enc);
+void sox_delete_effects_chain(sox_effects_chain_t *ecp);
+int sox_add_effect( sox_effects_chain_t * chain, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out);
+int sox_flow_effects(sox_effects_chain_t *, int (* callback)(sox_bool all_done, void * client_data), void * client_data);
+size_t sox_effects_clips(sox_effects_chain_t *);
+size_t sox_stop_effect(sox_effect_t *effp);
+void sox_push_effect_last(sox_effects_chain_t *chain, sox_effect_t *effp);
+sox_effect_t *sox_pop_effect_last(sox_effects_chain_t *chain);
+void sox_delete_effect(sox_effect_t *effp);
+void sox_delete_effect_last(sox_effects_chain_t *chain);
+void sox_delete_effects(sox_effects_chain_t *chain);
+
+/* The following routines are unique to the trim effect.
+ * sox_trim_get_start can be used to find what is the start
+ * of the trim operation as specified by the user.
+ * sox_trim_clear_start will reset what ever the user specified
+ * back to 0.
+ * These two can be used together to find out what the user
+ * wants to trim and use a sox_seek() operation instead. After
+ * sox_seek()'ing, you should set the trim option to 0.
+ */
+size_t sox_trim_get_start(sox_effect_t * effp);
+void sox_trim_clear_start(sox_effect_t * effp);
+size_t sox_crop_get_start(sox_effect_t * effp);
+void sox_crop_clear_start(sox_effect_t * effp);
+
+typedef int (* sox_playlist_callback_t)(void *, char *);
+sox_bool sox_is_playlist(char const * filename);
+int sox_parse_playlist(sox_playlist_callback_t callback, void * p, char const * const listname);
+
+char const * sox_strerror(int sox_errno);
+void sox_output_message(FILE *file, const char *filename, const char *fmt, va_list ap);
+
+/* WARNING BEGIN
+ *
+ * The items in this section are subject to instability. They only exist
+ * in public API because sox (the application) make use of them but
+ * may not be supported and may change rapidly.
+ */
+void lsx_fail(const char *, ...) PRINTF;
+void lsx_warn(const char *, ...) PRINTF;
+void lsx_report(const char *, ...) PRINTF;
+void lsx_debug(const char *, ...) PRINTF;
+
+#define lsx_fail sox_globals.subsystem=__FILE__,lsx_fail
+#define lsx_warn sox_globals.subsystem=__FILE__,lsx_warn
+#define lsx_report sox_globals.subsystem=__FILE__,lsx_report
+#define lsx_debug sox_globals.subsystem=__FILE__,lsx_debug
+
+typedef struct {char const *text; unsigned value;} lsx_enum_item;
+#define LSX_ENUM_ITEM(prefix, item) {#item, prefix##item},
+
+lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * lsx_enum_items, unsigned flags);
+#define LSX_FET_CASE 1
+lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * lsx_enum_items);
+int lsx_enum_option(int c, lsx_enum_item const * items);
+sox_bool lsx_strends(char const * str, char const * end);
+char const * lsx_find_file_extension(char const * pathname);
+char const * lsx_sigfigs3(double number);
+char const * lsx_sigfigs3p(double percentage);
+void *lsx_realloc(void *ptr, size_t newsize);
+int lsx_strcasecmp(const char * s1, const char * s2);
+int lsx_strncasecmp(char const * s1, char const * s2, size_t n);
+
+/* WARNING END */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/util/sox/src/sox_i.h b/util/sox/src/sox_i.h
new file mode 100644
index 00000000..1cfaa032
--- /dev/null
+++ b/util/sox/src/sox_i.h
@@ -0,0 +1,418 @@
+/* libSoX Internal header
+ *
+ * This file is meant for libSoX internal use only
+ *
+ * Copyright 2001-2008 Chris Bagwell and SoX Contributors
+ *
+ * This source code is freely redistributable and may be used for
+ * any purpose. This copyright notice must be maintained.
+ * Chris Bagwell And SoX Contributors are not responsible for
+ * the consequences of using this software.
+ */
+
+#ifndef SOX_I_H
+#define SOX_I_H
+
+#include "soxomp.h" /* Make this 1st in list (for soxconfig) */
+#if defined HAVE_FMEMOPEN
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#endif
+#include "sox.h"
+#include "util.h"
+
+#include <errno.h>
+
+#if defined(LSX_EFF_ALIAS)
+#undef lsx_debug
+#undef lsx_fail
+#undef lsx_report
+#undef lsx_warn
+#define lsx_debug sox_globals.subsystem=effp->handler.name,lsx_debug
+#define lsx_fail sox_globals.subsystem=effp->handler.name,lsx_fail
+#define lsx_report sox_globals.subsystem=effp->handler.name,lsx_report
+#define lsx_warn sox_globals.subsystem=effp->handler.name,lsx_warn
+#endif
+
+#define RANQD1 ranqd1(sox_globals.ranqd1)
+#define DRANQD1 dranqd1(sox_globals.ranqd1)
+
+typedef enum {SOX_SHORT, SOX_INT, SOX_FLOAT, SOX_DOUBLE} sox_data_t;
+typedef enum {SOX_WAVE_SINE, SOX_WAVE_TRIANGLE} lsx_wave_t;
+extern lsx_enum_item const lsx_wave_enum[];
+
+/* Define fseeko and ftello for platforms lacking them */
+#ifndef HAVE_FSEEKO
+#define fseeko fseek
+#define ftello ftell
+#endif
+
+#ifdef _FILE_OFFSET_BITS
+assert_static(sizeof(off_t) == _FILE_OFFSET_BITS >> 3, OFF_T_BUILD_PROBLEM);
+#endif
+
+#if defined __GNUC__
+#define FMT_size_t "zu"
+#elif defined _MSC_VER
+#define FMT_size_t "Iu"
+#else
+#define FMT_size_t "lu"
+#endif
+
+FILE * lsx_tmpfile(void);
+
+void lsx_debug_more(char const * fmt, ...) PRINTF;
+void lsx_debug_most(char const * fmt, ...) PRINTF;
+
+#define lsx_debug_more sox_globals.subsystem=__FILE__,lsx_debug_more
+#define lsx_debug_most sox_globals.subsystem=__FILE__,lsx_debug_most
+
+/* Digitise one cycle of a wave and store it as
+ * a table of samples of a specified data-type.
+ */
+void lsx_generate_wave_table(
+ lsx_wave_t wave_type,
+ sox_data_t data_type,
+ void * table, /* Really of type indicated by data_type. */
+ size_t table_size, /* Number of points on the x-axis. */
+ double min, /* Minimum value on the y-axis. (e.g. -1) */
+ double max, /* Maximum value on the y-axis. (e.g. +1) */
+ double phase); /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */
+char const * lsx_parsesamples(sox_rate_t rate, const char *str, size_t *samples, int def);
+int lsx_parse_note(char const * text, char * * end_ptr);
+double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key);
+#define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX)
+FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename);
+
+void lsx_prepare_spline3(double const * x, double const * y, int n,
+ double start_1d, double end_1d, double * y_2d);
+double lsx_spline3(double const * x, double const * y, double const * y_2d,
+ int n, double x1);
+
+double lsx_bessel_I_0(double x);
+int lsx_set_dft_length(int num_taps);
+void init_fft_cache(void);
+void clear_fft_cache(void);
+void lsx_safe_rdft(int len, int type, double * d);
+void lsx_safe_cdft(int len, int type, double * d);
+void lsx_power_spectrum(int n, double const * in, double * out);
+void lsx_power_spectrum_f(int n, float const * in, float * out);
+void lsx_apply_hann_f(float h[], const int num_points);
+void lsx_apply_hann(double h[], const int num_points);
+void lsx_apply_hamming(double h[], const int num_points);
+void lsx_apply_bartlett(double h[], const int num_points);
+void lsx_apply_blackman(double h[], const int num_points, double alpha);
+void lsx_apply_blackman_nutall(double h[], const int num_points);
+double lsx_kaiser_beta(double att);
+void lsx_apply_kaiser(double h[], const int num_points, double beta);
+double * lsx_make_lpf(int num_taps, double Fc, double beta, double scale, sox_bool dc_norm);
+int lsx_lpf_num_taps(double att, double tr_bw, int k);
+double * lsx_design_lpf(
+ double Fp, /* End of pass-band; ~= 0.01dB point */
+ double Fc, /* Start of stop-band */
+ double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */
+ sox_bool allow_aliasing,
+ double att, /* Stop-band attenuation in dB */
+ int * num_taps, /* (Single phase.) 0: value will be estimated */
+ int k); /* Number of phases; 0 for single-phase */
+void lsx_fir_to_phase(double * * h, int * len,
+ int * post_len, double phase0);
+#define LSX_TO_6dB .5869
+#define LSX_TO_3dB ((2/3.) * (.5 + LSX_TO_6dB))
+#define LSX_MAX_TBW0 36.
+#define LSX_MAX_TBW0A (LSX_MAX_TBW0 / (1 + LSX_TO_3dB))
+#define LSX_MAX_TBW3 floor(LSX_MAX_TBW0 * LSX_TO_3dB)
+#define LSX_MAX_TBW3A floor(LSX_MAX_TBW0A * LSX_TO_3dB)
+void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2);
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#define lsx_swapw(x) bswap_16(x)
+#define lsx_swapdw(x) bswap_32(x)
+#else
+#define lsx_swapw(uw) (((uw >> 8) | (uw << 8)) & 0xffff)
+#define lsx_swapdw(udw) ((udw >> 24) | ((udw >> 8) & 0xff00) | ((udw << 8) & 0xff0000) | (udw << 24))
+#endif
+
+
+
+/*------------------------ Implemented in libsoxio.c -------------------------*/
+
+/* Read and write basic data types from "ft" stream. */
+size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len);
+int lsx_skipbytes(sox_format_t * ft, size_t n);
+int lsx_padbytes(sox_format_t * ft, size_t n);
+size_t lsx_writebuf(sox_format_t * ft, void const *buf, size_t len);
+int lsx_reads(sox_format_t * ft, char *c, size_t len);
+int lsx_writes(sox_format_t * ft, char const * c);
+void lsx_set_signal_defaults(sox_format_t * ft);
+#define lsx_writechars(ft, chars, len) (lsx_writebuf(ft, chars, len) == len? SOX_SUCCESS : SOX_EOF)
+
+size_t lsx_read_3_buf(sox_format_t * ft, uint24_t *buf, size_t len);
+size_t lsx_read_b_buf(sox_format_t * ft, uint8_t *buf, size_t len);
+size_t lsx_read_df_buf(sox_format_t * ft, double *buf, size_t len);
+size_t lsx_read_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len);
+size_t lsx_read_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len);
+size_t lsx_read_f_buf(sox_format_t * ft, float *buf, size_t len);
+size_t lsx_read_w_buf(sox_format_t * ft, uint16_t *buf, size_t len);
+
+size_t lsx_write_3_buf(sox_format_t * ft, uint24_t *buf, size_t len);
+size_t lsx_write_b_buf(sox_format_t * ft, uint8_t *buf, size_t len);
+size_t lsx_write_df_buf(sox_format_t * ft, double *buf, size_t len);
+size_t lsx_write_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len);
+size_t lsx_write_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len);
+size_t lsx_write_f_buf(sox_format_t * ft, float *buf, size_t len);
+size_t lsx_write_w_buf(sox_format_t * ft, uint16_t *buf, size_t len);
+
+int lsx_read3(sox_format_t * ft, uint24_t * u3);
+int lsx_readb(sox_format_t * ft, uint8_t * ub);
+int lsx_readchars(sox_format_t * ft, char * chars, size_t len);
+int lsx_readdf(sox_format_t * ft, double * d);
+int lsx_readdw(sox_format_t * ft, uint32_t * udw);
+int lsx_readqw(sox_format_t * ft, uint64_t * udw);
+int lsx_readf(sox_format_t * ft, float * f);
+int lsx_readw(sox_format_t * ft, uint16_t * uw);
+
+#if 1 /* FIXME: use defines */
+UNUSED static int lsx_readsb(sox_format_t * ft, int8_t * sb)
+{return lsx_readb(ft, (uint8_t *)sb);}
+UNUSED static int lsx_readsw(sox_format_t * ft, int16_t * sw)
+{return lsx_readw(ft, (uint16_t *)sw);}
+#else
+#define lsx_readsb(ft, sb) lsx_readb(ft, (uint8_t *)sb)
+#define lsx_readsw(ft, sw) lsx_readb(ft, (uint16_t *)sw)
+#endif
+
+int lsx_write3(sox_format_t * ft, unsigned u3);
+int lsx_writeb(sox_format_t * ft, unsigned ub);
+int lsx_writedf(sox_format_t * ft, double d);
+int lsx_writedw(sox_format_t * ft, unsigned udw);
+int lsx_writeqw(sox_format_t * ft, uint64_t uqw);
+int lsx_writef(sox_format_t * ft, double f);
+int lsx_writew(sox_format_t * ft, unsigned uw);
+
+int lsx_writesb(sox_format_t * ft, signed);
+int lsx_writesw(sox_format_t * ft, signed);
+
+int lsx_eof(sox_format_t * ft);
+int lsx_error(sox_format_t * ft);
+int lsx_flush(sox_format_t * ft);
+int lsx_seeki(sox_format_t * ft, off_t offset, int whence);
+int lsx_unreadb(sox_format_t * ft, unsigned ub);
+size_t lsx_filelength(sox_format_t * ft);
+off_t lsx_tell(sox_format_t * ft);
+void lsx_clearerr(sox_format_t * ft);
+void lsx_rewind(sox_format_t * ft);
+
+int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample);
+
+void lsx_fail_errno(sox_format_t *, int, const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 3, 4)));
+#else
+;
+#endif
+
+typedef struct sox_formats_globals { /* Global parameters (for formats) */
+ sox_globals_t * global_info;
+} sox_formats_globals;
+
+
+
+/*------------------------------ File Handlers -------------------------------*/
+
+int lsx_check_read_params(sox_format_t * ft, unsigned channels,
+ sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
+ off_t num_samples, sox_bool check_length);
+#define LSX_FORMAT_HANDLER(name) \
+sox_format_handler_t const * lsx_##name##_format_fn(void); \
+sox_format_handler_t const * lsx_##name##_format_fn(void)
+#define div_bits(size, bits) (off_t)((double)(size) * 8 / bits)
+
+/* Raw I/O */
+int lsx_rawstartread(sox_format_t * ft);
+size_t lsx_rawread(sox_format_t * ft, sox_sample_t *buf, size_t nsamp);
+int lsx_rawstopread(sox_format_t * ft);
+int lsx_rawstartwrite(sox_format_t * ft);
+size_t lsx_rawwrite(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp);
+int lsx_rawseek(sox_format_t * ft, uint64_t offset);
+int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, sox_bool default_channels, sox_bool default_length, sox_encoding_t encoding, unsigned size);
+#define lsx_rawstartread(ft) lsx_rawstart(ft, sox_false, sox_false, sox_false, SOX_ENCODING_UNKNOWN, 0)
+#define lsx_rawstartwrite lsx_rawstartread
+#define lsx_rawstopread NULL
+#define lsx_rawstopwrite NULL
+
+extern sox_format_handler_t const * lsx_sndfile_format_fn(void);
+
+char * lsx_cat_comments(sox_comments_t comments);
+
+/*--------------------------------- Effects ----------------------------------*/
+
+int lsx_flow_copy(sox_effect_t * effp, const sox_sample_t * ibuf,
+ sox_sample_t * obuf, size_t * isamp, size_t * osamp);
+int lsx_usage(sox_effect_t * effp);
+char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n);
+#define EFFECT(f) extern sox_effect_handler_t const * lsx_##f##_effect_fn(void);
+#include "effects.h"
+#undef EFFECT
+
+#define NUMERIC_PARAMETER(name, min, max) { \
+ char * end_ptr; \
+ double d; \
+ if (argc == 0) break; \
+ d = strtod(*argv, &end_ptr); \
+ if (end_ptr != *argv) { \
+ if (d < min || d > max || *end_ptr != '\0') {\
+ lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
+ return lsx_usage(effp); \
+ } \
+ p->name = d; \
+ --argc, ++argv; \
+ } \
+}
+
+#define TEXTUAL_PARAMETER(name, enum_table) { \
+ lsx_enum_item const * e; \
+ if (argc == 0) break; \
+ e = lsx_find_enum_text(*argv, enum_table, 0); \
+ if (e != NULL) { \
+ p->name = e->value; \
+ --argc, ++argv; \
+ } \
+}
+
+#define GETOPT_NUMERIC(ch, name, min, max) case ch:{ \
+ char * end_ptr; \
+ double d = strtod(lsx_optarg, &end_ptr); \
+ if (end_ptr == lsx_optarg || d < min || d > max || *end_ptr != '\0') {\
+ lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
+ return lsx_usage(effp); \
+ } \
+ p->name = d; \
+ break; \
+}
+
+int lsx_effect_set_imin(sox_effect_t * effp, size_t imin);
+
+int lsx_effects_init(void);
+int lsx_effects_quit(void);
+
+/*--------------------------------- Dynamic Library ----------------------------------*/
+
+#if defined(HAVE_WIN32_LTDL_H)
+ #include "win32-ltdl.h"
+ #define HAVE_LIBLTDL 1
+ typedef lt_dlhandle lsx_dlhandle;
+#elif defined(HAVE_LIBLTDL)
+ #include <ltdl.h>
+ typedef lt_dlhandle lsx_dlhandle;
+#else
+ struct lsx_dlhandle_tag;
+ typedef struct lsx_dlhandle_tag *lsx_dlhandle;
+#endif
+
+typedef void (*lsx_dlptr)(void);
+
+typedef struct lsx_dlfunction_info
+{
+ const char* name;
+ lsx_dlptr static_func;
+ lsx_dlptr stub_func;
+} lsx_dlfunction_info;
+
+int lsx_open_dllibrary(
+ int show_error_on_failure,
+ const char* library_description,
+ const char * const library_names[],
+ const lsx_dlfunction_info func_infos[],
+ lsx_dlptr selected_funcs[],
+ lsx_dlhandle* pdl);
+
+void lsx_close_dllibrary(
+ lsx_dlhandle dl);
+
+#define LSX_DLENTRIES_APPLY__(entries, f, x) entries(f, x)
+
+#define LSX_DLENTRY_TO_PTR__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
+ func_return (*func_ptr) func_args;
+
+#define LSX_DLENTRIES_TO_FUNCTIONS__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
+ func_return func_name func_args;
+
+/* LSX_DLENTRIES_TO_PTRS: Given an ENTRIES macro and the name of the dlhandle
+ variable, declares the corresponding function pointer variables and the
+ dlhandle variable. */
+#define LSX_DLENTRIES_TO_PTRS(entries, dlhandle) \
+ LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRY_TO_PTR__, 0) \
+ lsx_dlhandle dlhandle
+
+/* LSX_DLENTRIES_TO_FUNCTIONS: Given an ENTRIES macro, declares the corresponding
+ functions. */
+#define LSX_DLENTRIES_TO_FUNCTIONS(entries) \
+ LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRIES_TO_FUNCTIONS__, 0)
+
+#define LSX_DLLIBRARY_OPEN1__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
+ { #func_name, (lsx_dlptr)(static_func), (lsx_dlptr)(stub_func) },
+
+#define LSX_DLLIBRARY_OPEN2__(ptr_container, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
+ (ptr_container)->func_ptr = (func_return (*)func_args)lsx_dlfunction_open_library_funcs[lsx_dlfunction_open_library_index++];
+
+/* LSX_DLLIBRARY_OPEN: Input an ENTRIES macro, the library's description,
+ a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }),
+ the name of the dlhandle variable, the name of the structure that contains
+ the function pointer and dlhandle variables, and the name of the variable in
+ which the result of the lsx_open_dllibrary call should be stored. This will
+ call lsx_open_dllibrary and copy the resulting function pointers into the
+ structure members. If the library cannot be opened, show a failure message. */
+#define LSX_DLLIBRARY_OPEN(ptr_container, dlhandle, entries, library_description, library_names, return_var) \
+ LSX_DLLIBRARY_TRYOPEN(1, ptr_container, dlhandle, entries, library_description, library_names, return_var)
+
+/* LSX_DLLIBRARY_TRYOPEN: Input an ENTRIES macro, the library's description,
+ a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }),
+ the name of the dlhandle variable, the name of the structure that contains
+ the function pointer and dlhandle variables, and the name of the variable in
+ which the result of the lsx_open_dllibrary call should be stored. This will
+ call lsx_open_dllibrary and copy the resulting function pointers into the
+ structure members. If the library cannot be opened, show a report or a failure
+ message, depending on whether error_on_failure is non-zero. */
+#define LSX_DLLIBRARY_TRYOPEN(error_on_failure, ptr_container, dlhandle, entries, library_description, library_names, return_var) \
+ do { \
+ lsx_dlfunction_info lsx_dlfunction_open_library_infos[] = { \
+ LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN1__, 0) \
+ {NULL,NULL,NULL} }; \
+ int lsx_dlfunction_open_library_index = 0; \
+ lsx_dlptr lsx_dlfunction_open_library_funcs[sizeof(lsx_dlfunction_open_library_infos)/sizeof(lsx_dlfunction_open_library_infos[0])]; \
+ (return_var) = lsx_open_dllibrary((error_on_failure), (library_description), (library_names), lsx_dlfunction_open_library_infos, lsx_dlfunction_open_library_funcs, &(ptr_container)->dlhandle); \
+ LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN2__, ptr_container) \
+ } while(0)
+
+#define LSX_DLLIBRARY_CLOSE(ptr_container, dlhandle) \
+ lsx_close_dllibrary((ptr_container)->dlhandle)
+
+ /* LSX_DLENTRY_STATIC: For use in creating an ENTRIES macro. func is
+ expected to be available at link time. If not present, link will fail. */
+#define LSX_DLENTRY_STATIC(f,x, ret, func, args) f(x, ret, func, args, func, NULL, func)
+
+ /* LSX_DLENTRY_DYNAMIC: For use in creating an ENTRIES macro. func need
+ not be available at link time (and if present, the link time version will
+ not be used). func will be loaded via dlsym. If this function is not
+ found in the shared library, the shared library will not be used. */
+#define LSX_DLENTRY_DYNAMIC(f,x, ret, func, args) f(x, ret, func, args, NULL, NULL, func)
+
+ /* LSX_DLENTRY_STUB: For use in creating an ENTRIES macro. func need not
+ be available at link time (and if present, the link time version will not
+ be used). If using DL_LAME, the func may be loaded via dlopen/dlsym, but
+ if not found, the shared library will still be used if all of the
+ non-stub functions are found. If the function is not found via dlsym (or
+ if we are not loading any shared libraries), the stub will be used. This
+ assumes that the name of the stub function is the name of the function +
+ "_stub". */
+#define LSX_DLENTRY_STUB(f,x, ret, func, args) f(x, ret, func, args, NULL, func##_stub, func)
+
+ /* LSX_DLFUNC_IS_STUB: returns true if the named function is a do-nothing
+ stub. Assumes that the name of the stub function is the name of the
+ function + "_stub". */
+#define LSX_DLFUNC_IS_STUB(ptr_container, func) ((ptr_container)->func == func##_stub)
+
+#endif
diff --git a/util/sox/src/soxconfig.h b/util/sox/src/soxconfig.h
new file mode 100644
index 00000000..01cb1f77
--- /dev/null
+++ b/util/sox/src/soxconfig.h
@@ -0,0 +1,402 @@
+/* src/soxconfig.h. Generated from soxconfig.h.in by configure. */
+/* src/soxconfig.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Define to dlopen() amrnb. */
+/* #undef DL_AMRNB */
+
+/* Define to dlopen() amrwb. */
+/* #undef DL_AMRWB */
+
+/* Define to dlopen() lame. */
+/* #undef DL_LAME */
+
+/* Define to dlopen() mad. */
+/* #undef DL_MAD */
+
+/* Define to dlopen() sndfile. */
+/* #undef DL_SNDFILE */
+
+/* Define if you are using an external GSM library */
+/* #undef EXTERNAL_GSM */
+
+/* Define if you are using an external LPC10 library */
+/* #undef EXTERNAL_LPC10 */
+
+/* Define to 1 if you have alsa. */
+#define HAVE_ALSA 1
+
+/* Define to 1 if you have amrnb. */
+/* #undef HAVE_AMRNB */
+
+/* Define to 1 if you have amrwb. */
+/* #undef HAVE_AMRWB */
+
+/* Define to 1 if you have the <amrwb/dec.h> header file. */
+/* #undef HAVE_AMRWB_DEC_H */
+
+/* Define to 1 if you have ao. */
+/* #undef HAVE_AO */
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#define HAVE_BYTESWAP_H 1
+
+/* Define to 1 if you have coreaudio. */
+/* #undef HAVE_COREAUDIO */
+
+/* 1 if DISTRO is defined */
+/* #undef HAVE_DISTRO */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have ffmpeg. */
+/* #undef HAVE_FFMPEG */
+
+/* Define to 1 if you have the <ffmpeg/avcodec.h> header file. */
+/* #undef HAVE_FFMPEG_AVCODEC_H */
+
+/* Define to 1 if you have the <ffmpeg/avformat.h> header file. */
+/* #undef HAVE_FFMPEG_AVFORMAT_H */
+
+/* Define to 1 if you have flac. */
+/* #undef HAVE_FLAC */
+
+/* Define to 1 if you have the `fmemopen' function. */
+#define HAVE_FMEMOPEN 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <glob.h> header file. */
+#define HAVE_GLOB_H 1
+
+/* Define to 1 if you have gsm. */
+#define HAVE_GSM 1
+
+/* Define to 1 if you have the <gsm/gsm.h> header file. */
+/* #undef HAVE_GSM_GSM_H */
+
+/* Define to 1 if you have the <gsm.h> header file. */
+/* #undef HAVE_GSM_H */
+
+/* Define to 1 if you have id3tag. */
+/* #undef HAVE_ID3TAG */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* 1 if should enable LADSPA */
+/* #define HAVE_LADSPA_H 1 */
+
+/* Define to 1 if you have lame 3.98 or greater. */
+/* #undef HAVE_LAME_398 */
+
+/* Define to 1 if lame 3.98 or newer ID3 tag support. */
+/* #undef HAVE_LAME_398_ID3TAG */
+
+/* Define to 1 if you have the <lame.h> header file. */
+/* #undef HAVE_LAME_H */
+
+/* Define to 1 if lame supports optional ID3 tags. */
+/* #undef HAVE_LAME_ID3TAG */
+
+/* Define to 1 if you have the <lame/lame.h> header file. */
+/* #undef HAVE_LAME_LAME_H */
+
+/* Define to 1 if you have the <libavcodec/avcodec.h> header file. */
+/* #undef HAVE_LIBAVCODEC_AVCODEC_H */
+
+/* Define to 1 if you have the <libavformat/avformat.h> header file. */
+/* #undef HAVE_LIBAVFORMAT_AVFORMAT_H */
+
+/* Define to 1 if you have libltdl */
+/* #define HAVE_LIBLTDL 1 */
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <libpng/png.h> header file. */
+/* #define HAVE_LIBPNG_PNG_H 1 */
+
+/* Define to 1 if you have lpc10. */
+/* #define HAVE_LPC10 1 */
+
+/* Define to 1 if you have the <lpc10.h> header file. */
+/* #undef HAVE_LPC10_H */
+
+/* Define to 1 if you have the <ltdl.h> header file. */
+/* #define HAVE_LTDL_H 1 */
+
+/* Define to 1 if you have the <machine/soundcard.h> header file. */
+/* #undef HAVE_MACHINE_SOUNDCARD_H */
+
+/* Define to 1 if you have the <mad.h> header file. */
+/* #define HAVE_MAD_H 1 */
+
+/* Define to 1 if you have magic. */
+/* #undef HAVE_MAGIC */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have mp3. */
+/* #define HAVE_MP3 1 */
+
+/* Define to 1 if you have oggvorbis. */
+/* #define HAVE_OGG_VORBIS 1 */
+
+/* Define to 1 if you have the <omp.h> header file. */
+/* #define HAVE_OMP_H 1 */
+
+/* Define to 1 if you have the <opencore-amrnb/interf_dec.h> header file. */
+/* #undef HAVE_OPENCORE_AMRNB_INTERF_DEC_H */
+
+/* Define to 1 if you have the <opencore-amrwb/dec_if.h> header file. */
+/* #undef HAVE_OPENCORE_AMRWB_DEC_IF_H */
+
+/* Define to 1 if you have GOMP. */
+/* #define HAVE_OPENMP 0 */
+
+/* Define to 1 if you have oss. */
+// #define HAVE_OSS 0
+
+/* Define to 1 if you have PNG. */
+// #define HAVE_PNG 0
+
+/* Define to 1 if you have the <png.h> header file. */
+// #define HAVE_PNG_H 0
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have pulseaudio. */
+// #define HAVE_PULSEAUDIO 1
+
+/* Define if you have libsndfile with SFC_SET_SCALE_FLOAT_INT_READ */
+/* #undef HAVE_SFC_SET_SCALE_FLOAT_INT_READ */
+
+/* Define if you have libsndfile with SFC_SFC_SET_SCALE_INT_FLOAT_WRITE */
+/* #undef HAVE_SFC_SET_SCALE_INT_FLOAT_WRITE */
+
+/* Define to 1 if you have sndfile. */
+/* #undef HAVE_SNDFILE */
+
+/* Define if you have libsndfile >= 1.0.12 */
+/* #undef HAVE_SNDFILE_1_0_12 */
+
+/* Define if you have libsndfile >= 1.0.18 */
+/* #undef HAVE_SNDFILE_1_0_18 */
+
+/* Define if you have <sndfile.h> */
+/* #undef HAVE_SNDFILE_H */
+
+/* Define to 1 if you have sndio. */
+/* #undef HAVE_SNDIO */
+
+/* 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 `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 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 sunaudio. */
+/* #undef HAVE_SUN_AUDIO */
+
+/* Define to 1 if you have the <sun/audioio.h> header file. */
+/* #undef HAVE_SUN_AUDIOIO_H */
+
+/* Define to 1 if you have the <sys/audioio.h> header file. */
+/* #undef HAVE_SYS_AUDIOIO_H */
+
+/* Define to 1 if you have the <sys/soundcard.h> header file. */
+// #define HAVE_SYS_SOUNDCARD_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/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_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 <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+// #define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have waveaudio. */
+/* #undef HAVE_WAVEAUDIO */
+
+/* Define to 1 if you have wavpack. */
+/* #undef HAVE_WAVPACK */
+
+/* Define to 1 to use win32 glob */
+/* #undef HAVE_WIN32_GLOB_H */
+
+/* Define to 1 to use internal win32 ltdl */
+/* #undef HAVE_WIN32_LTDL_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "sox"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "sox-devel@lists.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "SoX"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "SoX 14.3.2"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sox"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "14.3.2"
+
+/* The size of `char', as computed by sizeof. */
+/* #undef SIZEOF_CHAR */
+
+/* The size of `int', as computed by sizeof. */
+/* #undef SIZEOF_INT */
+
+/* The size of `long', as computed by sizeof. */
+/* #undef SIZEOF_LONG */
+
+/* The size of `short', as computed by sizeof. */
+/* #undef SIZEOF_SHORT */
+
+/* The size of `void*', as computed by sizeof. */
+/* #undef SIZEOF_VOIDP */
+
+/* Define to 1 if you have static alsa. */
+// #define STATIC_ALSA 1
+
+/* Define to 1 if you have static amrnb. */
+/* #undef STATIC_AMRNB */
+
+/* Define to 1 if you have static amrwb. */
+/* #undef STATIC_AMRWB */
+
+/* Define to 1 if you have static ao. */
+/* #undef STATIC_AO */
+
+/* Define to 1 if you have static coreaudio. */
+/* #undef STATIC_COREAUDIO */
+
+/* Define to 1 if you have static ffmpeg. */
+/* #undef STATIC_FFMPEG */
+
+/* Define to 1 if you have static flac. */
+/* #undef STATIC_FLAC */
+
+/* Define to 1 if you have static gsm. */
+// #define STATIC_GSM 1
+
+/* Define to 1 if you have static lpc10. */
+// #define STATIC_LPC10 1
+
+/* Define to 1 if you have static mp3. */
+// #define STATIC_MP3 1
+
+/* Define to 1 if you have static oggvorbis. */
+// #define STATIC_OGG_VORBIS 1
+
+/* Define to 1 if you have static oss. */
+// #define STATIC_OSS 1
+
+/* Define to 1 if you have static pulseaudio. */
+// #define STATIC_PULSEAUDIO 1
+
+/* Define to 1 if you have static sndfile. */
+/* #undef STATIC_SNDFILE */
+
+/* Define to 1 if you have static sndio. */
+/* #undef STATIC_SNDIO */
+
+/* Define to 1 if you have static sunaudio. */
+/* #undef STATIC_SUN_AUDIO */
+
+/* Define to 1 if you have static waveaudio. */
+/* #undef STATIC_WAVEAUDIO */
+
+/* Define to 1 if you have static wavpack. */
+/* #undef STATIC_WAVPACK */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "14.3.2"
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* # undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#define _LARGEFILE_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
diff --git a/util/sox/src/soxomp.h b/util/sox/src/soxomp.h
new file mode 100644
index 00000000..6fce07d9
--- /dev/null
+++ b/util/sox/src/soxomp.h
@@ -0,0 +1,38 @@
+#include "soxconfig.h"
+
+#ifdef HAVE_OPENMP
+ #include <omp.h>
+#else
+
+typedef int omp_lock_t;
+typedef int omp_nest_lock_t;
+
+#define omp_set_num_threads(int) (void)0
+#define omp_get_num_threads() 1
+#define omp_get_max_threads() 1
+#define omp_get_thread_num() 0
+#define omp_get_num_procs() 1
+#define omp_in_parallel() 1
+
+#define omp_set_dynamic(int) (void)0
+#define omp_get_dynamic() 0
+
+#define omp_set_nested(int) (void)0
+#define omp_get_nested() 0
+
+#define omp_init_lock(omp_lock_t) (void)0
+#define omp_destroy_lock(omp_lock_t) (void)0
+#define omp_set_lock(omp_lock_t) (void)0
+#define omp_unset_lock(omp_lock_t) (void)0
+#define omp_test_lock(omp_lock_t) 0
+
+#define omp_init_nest_lock(omp_nest_lock_t) (void)0
+#define omp_destroy_nest_lock(omp_nest_lock_t) (void)0
+#define omp_set_nest_lock(omp_nest_lock_t) (void)0
+#define omp_unset_nest_lock(omp_nest_lock_t) (void)0
+#define omp_test_nest_lock(omp_nest_lock_t) 0
+
+#define omp_get_wtime() 0
+#define omp_get_wtick() 0
+
+#endif
diff --git a/util/sox/src/soxstdint.h b/util/sox/src/soxstdint.h
new file mode 100644
index 00000000..25c11114
--- /dev/null
+++ b/util/sox/src/soxstdint.h
@@ -0,0 +1,9 @@
+#ifndef _SOX_SRC_SOXSTDINT_H
+#define _SOX_SRC_SOXSTDINT_H 1
+#ifndef _GENERATED_STDINT_H
+#define _GENERATED_STDINT_H "sox 14.3.2"
+/* generated using gnu compiler gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 */
+#define _STDINT_HAVE_STDINT_H 1
+#include <stdint.h>
+#endif
+#endif
diff --git a/util/sox/src/util.h b/util/sox/src/util.h
new file mode 100644
index 00000000..a6d9675c
--- /dev/null
+++ b/util/sox/src/util.h
@@ -0,0 +1,180 @@
+/* General purpose, i.e. non SoX specific, utility functions and macros.
+ *
+ * (c) 2006-8 Chris Bagwell and SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h> /* For off_t not found in stdio.h */
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h> /* Needs to be included before we redefine off_t. */
+#endif
+
+#include "xmalloc.h"
+
+/*---------------------------- Portability stuff -----------------------------*/
+
+#ifdef __GNUC__
+#define NORET __attribute__((noreturn))
+#define PRINTF __attribute__ ((format (printf, 1, 2)))
+#define UNUSED __attribute__ ((unused))
+#else
+#define NORET
+#define PRINTF
+#define UNUSED
+#endif
+
+#ifdef _MSC_VER
+
+#define __STDC__ 1
+#define O_BINARY _O_BINARY
+#define O_CREAT _O_CREAT
+#define O_RDWR _O_RDWR
+#define O_TRUNC _O_TRUNC
+#define S_IFMT _S_IFMT
+#define S_IFREG _S_IFREG
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+#define close _close
+#define dup _dup
+#define fdopen _fdopen
+#define fileno _fileno
+
+#ifdef _fstati64
+#define fstat _fstati64
+#else
+#define fstat _fstat
+#endif
+
+#define ftime _ftime
+#define inline __inline
+#define isatty _isatty
+#define kbhit _kbhit
+#define mktemp _mktemp
+#define off_t _off_t
+#define open _open
+#define pclose _pclose
+#define popen _popen
+#define setmode _setmode
+#define snprintf _snprintf
+
+#ifdef _stati64
+#define stat _stati64
+#else
+#define stat _stat
+#endif
+
+#define strdup _strdup
+#define timeb _timeb
+#define unlink _unlink
+
+#if defined(HAVE__FSEEKI64) && !defined(HAVE_FSEEKO)
+#undef off_t
+#define fseeko _fseeki64
+#define ftello _ftelli64
+#define off_t __int64
+#define HAVE_FSEEKO 1
+#endif
+
+#elif defined(__MINGW32__)
+
+#if !defined(HAVE_FSEEKO)
+#undef off_t
+#define fseeko fseeko64
+#define fstat _fstati64
+#define ftello ftello64
+#define off_t off64_t
+#define stat _stati64
+#define HAVE_FSEEKO 1
+#endif
+
+#endif
+
+#if defined(DOS) || defined(WIN32) || defined(__NT__) || defined(__DJGPP__) || defined(__OS2__)
+ #define LAST_SLASH(path) max(strrchr(path, '/'), strrchr(path, '\\'))
+ #define IS_ABSOLUTE(path) ((path)[0] == '/' || (path)[0] == '\\' || (path)[1] == ':')
+ #define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+ #define LAST_SLASH(path) strrchr(path, '/')
+ #define IS_ABSOLUTE(path) ((path)[0] == '/')
+ #define SET_BINARY_MODE(file)
+#endif
+
+#ifdef WORDS_BIGENDIAN
+ #define MACHINE_IS_BIGENDIAN 1
+ #define MACHINE_IS_LITTLEENDIAN 0
+#else
+ #define MACHINE_IS_BIGENDIAN 0
+ #define MACHINE_IS_LITTLEENDIAN 1
+#endif
+
+/*--------------------------- Language extensions ----------------------------*/
+
+/* Compile-time ("static") assertion */
+/* e.g. assert_static(sizeof(int) >= 4, int_type_too_small) */
+#define assert_static(e,f) enum {assert_static__##f = 1/(e)}
+#define array_length(a) (sizeof(a)/sizeof(a[0]))
+#define field_offset(type, field) ((size_t)&(((type *)0)->field))
+#define unless(x) if (!(x))
+
+/*------------------------------- Maths stuff --------------------------------*/
+
+#include <math.h>
+
+#ifdef min
+#undef min
+#endif
+#define min(a, b) ((a) <= (b) ? (a) : (b))
+
+#ifdef max
+#undef max
+#endif
+#define max(a, b) ((a) >= (b) ? (a) : (b))
+
+#define range_limit(x, lower, upper) (min(max(x, lower), upper))
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#endif
+#ifndef M_LN10
+#define M_LN10 2.30258509299404568402 /* natural log of 10 */
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 sqrt(2.)
+#endif
+
+#define sqr(a) ((a) * (a))
+#define sign(x) ((x) < 0? -1 : 1)
+
+/* Numerical Recipes in C, p. 284 */
+#define ranqd1(x) ((x) = 1664525L * (x) + 1013904223L) /* int32_t x */
+#define dranqd1(x) (ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */
+
+#define dB_to_linear(x) exp((x) * M_LN10 * 0.05)
+#define linear_to_dB(x) (log10(x) * 20)
+
+extern int lsx_strcasecmp(const char *s1, const char *st);
+extern int lsx_strncasecmp(char const *s1, char const *s2, size_t n);
+
+#ifndef HAVE_STRCASECMP
+#define strcasecmp(s1, s2) lsx_strcasecmp((s1), (s2))
+#define strncasecmp(s1, s2, n) lsx_strncasecmp((s1), (s2), (n))
+#endif
diff --git a/util/sox/src/xmalloc.h b/util/sox/src/xmalloc.h
new file mode 100644
index 00000000..b2a6d026
--- /dev/null
+++ b/util/sox/src/xmalloc.h
@@ -0,0 +1,34 @@
+/* libSoX Memory allocation functions
+ *
+ * Copyright (c) 2005-2006 Reuben Thomas. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LSX_MALLOC_H
+#define LSX_MALLOC_H
+
+#include <stddef.h>
+#include <string.h>
+
+#define lsx_malloc(size) lsx_realloc(NULL, (size))
+#define lsx_calloc(n,s) ((n)*(s)? memset(lsx_malloc((n)*(s)),0,(n)*(s)) : NULL)
+#define lsx_Calloc(v,n) v = lsx_calloc(n,sizeof(*(v)))
+#define lsx_strdup(p) ((p)? strcpy((char *)lsx_malloc(strlen(p) + 1), p) : NULL)
+#define lsx_memdup(p,s) ((p)? memcpy(lsx_malloc(s), p, s) : NULL)
+#define lsx_valloc(v,n) v = lsx_malloc((n)*sizeof(*(v)))
+#define lsx_revalloc(v,n) v = lsx_realloc(v, (n)*sizeof(*(v)))
+
+#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:12 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68316
Default Alt Text
(144 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline