Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
144 KB
Referenced Files
None
Subscribers
None
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

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)

Event Timeline