mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
integrated linux support
This commit is contained in:
parent
3502a58f57
commit
c29cd37138
@ -45,18 +45,23 @@
|
|||||||
|
|
||||||
#end lib_target
|
#end lib_target
|
||||||
|
|
||||||
// #begin lib_target
|
#begin lib_target
|
||||||
// #define TARGET audio_load_st
|
#define TARGET audio_load_st
|
||||||
// #define LOCAL_LIBS \
|
#define USE_SOXST yes
|
||||||
// audio
|
#define LOCAL_LIBS \
|
||||||
//
|
audio
|
||||||
// #define SOURCES \
|
|
||||||
// audio_load_st.cxx
|
#define SOURCES \
|
||||||
//
|
audio_load_st.cxx
|
||||||
// #end lib_target
|
|
||||||
|
#end lib_target
|
||||||
|
|
||||||
#begin test_bin_target
|
#begin test_bin_target
|
||||||
#define TARGET test_audio
|
#define TARGET test_audio
|
||||||
|
#define LOCAL_LIBS \
|
||||||
|
audio
|
||||||
|
#define OTHER_LIBS \
|
||||||
|
$[OTHER_LIBS] pystub
|
||||||
|
|
||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
test_audio.cxx
|
test_audio.cxx
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#include <ipc_thread.h>
|
#include <ipc_thread.h>
|
||||||
#include <ipc_mutex.h>
|
#include <ipc_mutex.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/soundcard.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
typedef set<Buffer*> BufferSet;
|
typedef set<Buffer*> BufferSet;
|
||||||
|
|
||||||
@ -21,11 +24,11 @@ static byte* buffer1;
|
|||||||
static byte* buffer2;
|
static byte* buffer2;
|
||||||
static byte* current_buffer;
|
static byte* current_buffer;
|
||||||
static byte* back_buffer;
|
static byte* back_buffer;
|
||||||
static byte* zero_buffer;
|
byte* zero_buffer;
|
||||||
static byte* scratch_buffer;
|
static byte* scratch_buffer;
|
||||||
static byte* fetch_buffer;
|
static byte* fetch_buffer;
|
||||||
static int want_buffers, have_buffers;
|
static int want_buffers = 0, have_buffers = 0;
|
||||||
static bool initializing = false;
|
static bool initializing = true;
|
||||||
static int output_fd;
|
static int output_fd;
|
||||||
static thread* update_thread;
|
static thread* update_thread;
|
||||||
static int sample_size = sizeof(short);
|
static int sample_size = sizeof(short);
|
||||||
@ -98,8 +101,8 @@ static void mix_in(byte* buf, byte* from, float vol, float pan) {
|
|||||||
signed short in_right = read_buffer(from, i+1);
|
signed short in_right = read_buffer(from, i+1);
|
||||||
|
|
||||||
// figure out panning at some point
|
// figure out panning at some point
|
||||||
in_left *= vol;
|
in_left = (short int)(in_left * vol);
|
||||||
in_right *= vol;
|
in_right = (short int)(in_right * vol);
|
||||||
|
|
||||||
// compute mixed values
|
// compute mixed values
|
||||||
left = sound_clamp(left+in_left);
|
left = sound_clamp(left+in_left);
|
||||||
@ -115,7 +118,7 @@ static void mix_buffer(byte* buf) {
|
|||||||
memcpy(scratch_buffer, zero_buffer, audio_buffer_size);
|
memcpy(scratch_buffer, zero_buffer, audio_buffer_size);
|
||||||
// do stuff
|
// do stuff
|
||||||
for (BufferSet::iterator i=buffers.begin(); i!=buffers.end(); ++i)
|
for (BufferSet::iterator i=buffers.begin(); i!=buffers.end(); ++i)
|
||||||
min_in(scratch, (*i)->get_buffer(fetch_buffer), 1., 0.);
|
mix_in(scratch_buffer, (*i)->get_buffer(fetch_buffer), 1., 0.);
|
||||||
BufferSet to_del;
|
BufferSet to_del;
|
||||||
for (BufferSet::iterator j=buffers.begin(); j!=buffers.end(); ++j)
|
for (BufferSet::iterator j=buffers.begin(); j!=buffers.end(); ++j)
|
||||||
if ((*j)->is_done())
|
if ((*j)->is_done())
|
||||||
@ -149,6 +152,9 @@ static void update_linux(void) {
|
|||||||
// mix 2 buffers and put them in place.
|
// mix 2 buffers and put them in place.
|
||||||
mix_buffer(current_buffer);
|
mix_buffer(current_buffer);
|
||||||
mix_buffer(back_buffer);
|
mix_buffer(back_buffer);
|
||||||
|
if (initializing)
|
||||||
|
audio_cat->debug() << "mixed 2 buffers, want is currently at ("
|
||||||
|
<< want_buffers << ")" << endl;
|
||||||
initializing = false;
|
initializing = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -157,7 +163,7 @@ static void update_linux(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void internal_update(void*) {
|
static void internal_update(void*) {
|
||||||
if ((output_fd = open(audio_device, O_WRONLY, 0)) == -1) {
|
if ((output_fd = open(audio_device->c_str(), O_WRONLY, 0)) == -1) {
|
||||||
audio_cat->error() << "could not open '" << audio_device << "'" << endl;
|
audio_cat->error() << "could not open '" << audio_device << "'" << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -221,7 +227,7 @@ static void initialize(void) {
|
|||||||
|
|
||||||
audio_cat->info() << "spawning internal update thread" << endl;
|
audio_cat->info() << "spawning internal update thread" << endl;
|
||||||
update_thread = thread::create(internal_update, (void*)0L,
|
update_thread = thread::create(internal_update, (void*)0L,
|
||||||
thread_PRIORITY_NORMAL);
|
thread::PRIORITY_NORMAL);
|
||||||
|
|
||||||
AudioManager::set_update_func(update_linux);
|
AudioManager::set_update_func(update_linux);
|
||||||
have_initialized = true;
|
have_initialized = true;
|
||||||
|
@ -11,7 +11,14 @@
|
|||||||
#ifndef __AUDIO_LINUX_TRAITS_H__
|
#ifndef __AUDIO_LINUX_TRAITS_H__
|
||||||
#define __AUDIO_LINUX_TRAITS_H__
|
#define __AUDIO_LINUX_TRAITS_H__
|
||||||
|
|
||||||
|
#include "config_audio.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_DEFINED_BYTE
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
#define HAVE_DEFINED_BYTE
|
||||||
|
#endif /* HAVE_DEFINED_BYTE */
|
||||||
|
|
||||||
|
extern byte* zero_buffer;
|
||||||
|
|
||||||
class EXPCL_PANDA Buffer {
|
class EXPCL_PANDA Buffer {
|
||||||
private:
|
private:
|
||||||
@ -19,15 +26,21 @@ private:
|
|||||||
unsigned long _size;
|
unsigned long _size;
|
||||||
unsigned long _pos;
|
unsigned long _pos;
|
||||||
bool _done;
|
bool _done;
|
||||||
|
|
||||||
|
INLINE unsigned long buffer_min(unsigned long a, unsigned long b) {
|
||||||
|
return (a<b)?a:b;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
INLINE Buffer(byte* data, unsigned long size) : _data(data), _size(size),
|
INLINE Buffer(byte* data, unsigned long size) : _data(data), _size(size),
|
||||||
_pos(0), _done(false) {}
|
_pos(0), _done(false) {}
|
||||||
INLINE byte* get_buffer(byte* buf) {
|
INLINE byte* get_buffer(byte* buf) {
|
||||||
memcpy(buf, &_data[_pos], audio_buffer_size);
|
unsigned long copy_size = buffer_min(_size-_pos, audio_buffer_size);
|
||||||
_pos += audio_buffer_size;
|
unsigned long residue = audio_buffer_size - copy_size;
|
||||||
if (_pos > _size) {
|
memcpy(buf, &_data[_pos], copy_size);
|
||||||
|
_pos += copy_size;
|
||||||
|
if (residue != 0) {
|
||||||
_pos -= _size;
|
_pos -= _size;
|
||||||
memcpy(&buf[audio_buffer_size-_pos-1], zero_buffer, _pos);
|
memcpy(&buf[copy_size], zero_buffer, residue);
|
||||||
_done = true;
|
_done = true;
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
@ -36,7 +49,7 @@ public:
|
|||||||
return _done;
|
return _done;
|
||||||
}
|
}
|
||||||
INLINE unsigned long get_size(void) const {
|
INLINE unsigned long get_size(void) const {
|
||||||
return _size
|
return _size;
|
||||||
}
|
}
|
||||||
INLINE void reset(void) {
|
INLINE void reset(void) {
|
||||||
_done = false;
|
_done = false;
|
||||||
@ -57,7 +70,7 @@ public:
|
|||||||
static void destroy(AudioTraits::SampleClass*);
|
static void destroy(AudioTraits::SampleClass*);
|
||||||
public:
|
public:
|
||||||
// used by the loader
|
// used by the loader
|
||||||
static LinuxSample* load_raw(byte*, unsigned long)
|
static LinuxSample* load_raw(byte*, unsigned long);
|
||||||
// used by the players
|
// used by the players
|
||||||
INLINE Buffer* get_data(void);
|
INLINE Buffer* get_data(void);
|
||||||
};
|
};
|
||||||
|
@ -8,11 +8,16 @@
|
|||||||
#include "config_audio.h"
|
#include "config_audio.h"
|
||||||
#include "audio_trait.h"
|
#include "audio_trait.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SOXST
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
#include <sox/st.h>
|
#include <sox/st.h>
|
||||||
#include <sox/patchlvl.h>
|
#include <sox/patchlvl.h>
|
||||||
|
}
|
||||||
|
|
||||||
#if (PATCHLEVEL == 16)
|
#if (PATCHLEVEL == 16)
|
||||||
#define FORMATS formats
|
#define FORMATS formats
|
||||||
|
#define ENCODEFIELD style
|
||||||
#define EFFECTS_TYPE struct effect
|
#define EFFECTS_TYPE struct effect
|
||||||
#define STREAM_TYPE struct soundstream
|
#define STREAM_TYPE struct soundstream
|
||||||
#define GETTYPE gettype
|
#define GETTYPE gettype
|
||||||
@ -21,10 +26,12 @@
|
|||||||
#define SIZES sizes
|
#define SIZES sizes
|
||||||
#define ENCODING styles
|
#define ENCODING styles
|
||||||
#define COPYFORMAT copyformat
|
#define COPYFORMAT copyformat
|
||||||
#define GETEFFECT geteffect
|
#define UPDATEEFFECT(a, b, c, d) \
|
||||||
#define UPDATEEFFECT(a, b, c, d)
|
(a)->ininfo.channels = (b)->info.channels; \
|
||||||
|
(a)->outinfo.channels = (c)->info.channels;
|
||||||
#else /* PATCHLEVEL != 16 */
|
#else /* PATCHLEVEL != 16 */
|
||||||
#define FORMATS st_formats
|
#define FORMATS st_formats
|
||||||
|
#define ENCODEFIELD encoding
|
||||||
#define EFFECTS_TYPE struct st_effect
|
#define EFFECTS_TYPE struct st_effect
|
||||||
#define STREAM_TYPE struct st_soundstream
|
#define STREAM_TYPE struct st_soundstream
|
||||||
#define GETTYPE st_gettype
|
#define GETTYPE st_gettype
|
||||||
@ -33,45 +40,64 @@
|
|||||||
#define SIZES st_sizes_str
|
#define SIZES st_sizes_str
|
||||||
#define ENCODING st_encodings_str
|
#define ENCODING st_encodings_str
|
||||||
#define COPYFORMAT st_copyformat
|
#define COPYFORMAT st_copyformat
|
||||||
#define GETEFFECT st_geteffect
|
|
||||||
#define UPDATEEFFECT st_updateeffect
|
#define UPDATEEFFECT st_updateeffect
|
||||||
#endif /* PATCHLEVEL */
|
#endif /* PATCHLEVEL */
|
||||||
|
|
||||||
|
#endif /* HAVE_SOXST */
|
||||||
|
|
||||||
Configure(audio_load_st);
|
Configure(audio_load_st);
|
||||||
|
|
||||||
|
#ifdef HAVE_SOXST
|
||||||
|
|
||||||
// the effects we will be using are to change the rate and number of channels
|
// the effects we will be using are to change the rate and number of channels
|
||||||
static EFFECTS_TYPE efftab[5]; // left/mono channel effects
|
static EFFECTS_TYPE efftab[5]; // left/mono channel effects
|
||||||
static EFFECTS_TYPE efftabR[5]; // right channel effects
|
static EFFECTS_TYPE efftabR[5]; // right channel effects
|
||||||
static int neffects; // how many effects are in action
|
static int neffects; // how many effects are in action
|
||||||
|
|
||||||
static STREAM_TYPE informat; // holder for the input
|
static STREAM_TYPE iformat; // holder for the input
|
||||||
static STREAM_TYPE outformat; // holder for fake output;
|
static STREAM_TYPE oformat; // holder for fake output;
|
||||||
|
|
||||||
INLINE static void init_stream(void) {
|
INLINE static void init_stream(void) {
|
||||||
informat.info.rate = 0;
|
iformat.info.rate = 0;
|
||||||
informat.info.size = -1;
|
iformat.info.size = -1;
|
||||||
informat.info.encoding = -1;
|
iformat.info.ENCODEFIELD = -1;
|
||||||
informat.info.channels = -1;
|
iformat.info.channels = -1;
|
||||||
informat.comment = (char*)0L;
|
iformat.comment = (char*)0L;
|
||||||
informat.swap = 0;
|
iformat.swap = 0;
|
||||||
informat.filetype = (char*)0L;
|
iformat.filetype = (char*)0L;
|
||||||
informat.fp = stdin;
|
iformat.fp = stdin;
|
||||||
informat.filename = "input";
|
iformat.filename = "input";
|
||||||
|
|
||||||
outformat.info.rate = audio_mix_freq;
|
oformat.info.rate = audio_mix_freq;
|
||||||
outformat.info.size = -1;
|
oformat.info.size = -1;
|
||||||
outformat.info.encoding = -1;
|
oformat.info.ENCODEFIELD = -1;
|
||||||
outformat.info.channels = 2;
|
oformat.info.channels = 2;
|
||||||
outformat.comment = (char*)0L;
|
oformat.comment = (char*)0L;
|
||||||
outformat.swap = 0;
|
oformat.swap = 0;
|
||||||
outformat.filetype = (char*)0L;
|
oformat.filetype = (char*)0L;
|
||||||
outformat.fp = stdout;
|
oformat.fp = stdout;
|
||||||
outformat.filename = "output";
|
oformat.filename = "output";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE static void compat_geteffect(EFFECTS_TYPE* eff, const char* name) {
|
||||||
|
#if (PATCHLEVEL == 16)
|
||||||
|
eff->name = (char*)name;
|
||||||
|
geteffect(eff);
|
||||||
|
#else /* PATCHLEVEL == 16 */
|
||||||
|
st_geteffect(eff, name);
|
||||||
|
#endif /* PATCHLEVEL == 16 */
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void effOptFunc(EFFECTS_TYPE*, int, char**);
|
||||||
|
#ifndef HAVE_DEFINED_BYTE
|
||||||
|
typedef unsigned char byte;
|
||||||
|
#define HAVE_DEFINED_BYTE
|
||||||
|
#endif /* HAVE_DEFINED_BYTE */
|
||||||
|
|
||||||
INLINE static void check_effects(void) {
|
INLINE static void check_effects(void) {
|
||||||
bool needchan = (informat.info.rate != audio_mix_freq);
|
bool needrate = (iformat.info.rate != audio_mix_freq);
|
||||||
bool needrate = (informat.info.channels != 2);
|
bool needchan = (iformat.info.channels != 2);
|
||||||
|
effOptFunc* func;
|
||||||
|
|
||||||
// efftab[0] is always the input stream and always exists
|
// efftab[0] is always the input stream and always exists
|
||||||
neffects = 1;
|
neffects = 1;
|
||||||
@ -79,11 +105,12 @@ INLINE static void check_effects(void) {
|
|||||||
// if reducing the number of samples, it is faster to run all effects
|
// if reducing the number of samples, it is faster to run all effects
|
||||||
// after the resample effect
|
// after the resample effect
|
||||||
if (needrate) {
|
if (needrate) {
|
||||||
GETEFFECT(&efftab[neffects], "resample");
|
compat_geteffect(&efftab[neffects], "resample");
|
||||||
// setup and give default opts
|
// setup and give default opts
|
||||||
(*efftab[neffects].h->getopts)(&efftab[neffects],(int)0,(char**)0L);
|
func = (effOptFunc*)(efftab[neffects].h->getopts);
|
||||||
|
(*func)(&efftab[neffects],(int)0,(char**)0L);
|
||||||
// copy format info to effect table
|
// copy format info to effect table
|
||||||
UPDATEEFFECT(&efftab[neffects], &informat, &outformat, 0);
|
UPDATEEFFECT(&efftab[neffects], &iformat, &oformat, 0);
|
||||||
// rate can't handle multiple channels so be sure and account for that
|
// rate can't handle multiple channels so be sure and account for that
|
||||||
if (efftab[neffects].ininfo.channels > 1)
|
if (efftab[neffects].ininfo.channels > 1)
|
||||||
memcpy(&efftabR[neffects], &efftab[neffects], sizeof(EFFECTS_TYPE));
|
memcpy(&efftabR[neffects], &efftab[neffects], sizeof(EFFECTS_TYPE));
|
||||||
@ -92,53 +119,169 @@ INLINE static void check_effects(void) {
|
|||||||
// if we ever have more then 2 channels in an input file, we will need to
|
// if we ever have more then 2 channels in an input file, we will need to
|
||||||
// deal with that somewhere here
|
// deal with that somewhere here
|
||||||
if (needchan) {
|
if (needchan) {
|
||||||
GETEFFECT(&efftab[neffects], "avg");
|
compat_geteffect(&efftab[neffects], "avg");
|
||||||
//setup and give default opts
|
//setup and give default opts
|
||||||
(*efftab[neffects].h->getopts)(&efftab[neffects],(int)0,(char**)0L);
|
func = (effOptFunc*)(efftab[neffects].h->getopts);
|
||||||
|
(*func)(&efftab[neffects],(int)0,(char**)0L);
|
||||||
// copy format info to effect table
|
// copy format info to effect table
|
||||||
UPDATEEFFECT(&efftab[neffects], &informat, &outformat, 0);
|
UPDATEEFFECT(&efftab[neffects], &iformat, &oformat, 0);
|
||||||
++neffects;
|
++neffects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte* read_file(Filename filename) {
|
typedef void effFlowFunc(EFFECTS_TYPE*, LONG*, LONG*, LONG*, LONG*);
|
||||||
|
|
||||||
|
static LONG ibufl[BUFSIZ/2];
|
||||||
|
static LONG ibufr[BUFSIZ/2];
|
||||||
|
static LONG obufl[BUFSIZ/2];
|
||||||
|
static LONG obufr[BUFSIZ/2];
|
||||||
|
|
||||||
|
static int flow_effect(int e) {
|
||||||
|
LONG i, done, idone, odone, idonel, odonel, idoner, odoner;
|
||||||
|
LONG *ibuf, *obuf;
|
||||||
|
effFlowFunc* eflow;
|
||||||
|
|
||||||
|
// is there any input data?
|
||||||
|
if (efftab[e-1].odone == efftab[e-1].olen)
|
||||||
|
return 0;
|
||||||
|
if (!efftabR[e].name) {
|
||||||
|
// no stereo data, or effect can handle stereo data. so run effect
|
||||||
|
// over the entire buffer
|
||||||
|
idone = efftab[e-1].olen - efftab[e-1].odone;
|
||||||
|
odone = BUFSIZ;
|
||||||
|
eflow = (effFlowFunc*)(efftab[e].h->flow);
|
||||||
|
(*eflow)(&efftab[e], &efftab[e-1].obuf[efftab[e-1].odone], efftab[e].obuf,
|
||||||
|
&idone, &odone);
|
||||||
|
efftab[e-1].odone += idone;
|
||||||
|
efftab[e].odone = 0;
|
||||||
|
efftab[e].olen = odone;
|
||||||
|
done = idone + odone;
|
||||||
|
} else {
|
||||||
|
// put stereo data in two seperate buffers and run effect on each of them
|
||||||
|
idone = efftab[e-1].olen - efftab[e-1].odone;
|
||||||
|
odone = BUFSIZ;
|
||||||
|
ibuf = &efftab[e-1].obuf[efftab[e-1].odone];
|
||||||
|
for (i=0; i<idone; i+=2) {
|
||||||
|
ibufl[i/2] = *ibuf++;
|
||||||
|
ibufr[i/2] = *ibuf++;
|
||||||
|
}
|
||||||
|
// left
|
||||||
|
idonel = (idone + 1)/2; // odd-length logic
|
||||||
|
odonel = odone / 2;
|
||||||
|
eflow = (effFlowFunc*)(efftab[e].h->flow);
|
||||||
|
(*eflow)(&efftab[e], ibufl, obufl, &idonel, &odonel);
|
||||||
|
// right
|
||||||
|
idoner = idone/2; // odd-length logic
|
||||||
|
odoner = odone/2;
|
||||||
|
eflow = (effFlowFunc*)(efftabR[e].h->flow);
|
||||||
|
(*eflow)(&efftabR[e], ibufr, obufr, &idoner, &odoner);
|
||||||
|
obuf = efftab[e].obuf;
|
||||||
|
// this loop implies that left and right effects will always output
|
||||||
|
// the same amount of data
|
||||||
|
for (i=0; i<odoner; i++) {
|
||||||
|
*obuf++ = obufl[i];
|
||||||
|
*obuf++ = obufr[i];
|
||||||
|
}
|
||||||
|
efftab[e-1].odone += idonel + idoner;
|
||||||
|
efftab[e].odone = 0;
|
||||||
|
efftab[e].olen = odonel + odoner;
|
||||||
|
done = idonel + idoner + odonel + odoner;
|
||||||
|
}
|
||||||
|
if (done == 0)
|
||||||
|
audio_cat->error() << "Effect took & gave no samples!" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void effDrainFunc(EFFECTS_TYPE*, LONG*, LONG*);
|
||||||
|
|
||||||
|
static int drain_effect(int e) {
|
||||||
|
LONG i, olen, olenl, olenr;
|
||||||
|
LONG *obuf;
|
||||||
|
effDrainFunc* edrain;
|
||||||
|
|
||||||
|
if (!efftabR[e].name) {
|
||||||
|
efftab[e].olen = BUFSIZ;
|
||||||
|
edrain = (effDrainFunc*)(efftab[e].h->drain);
|
||||||
|
(*edrain)(&efftab[e], efftab[e].obuf, &efftab[e].olen);
|
||||||
|
} else {
|
||||||
|
olen = BUFSIZ;
|
||||||
|
// left
|
||||||
|
olenl = olen / 2;
|
||||||
|
edrain = (effDrainFunc*)(efftab[e].h->drain);
|
||||||
|
(*edrain)(&efftab[e], obufl, &olenl);
|
||||||
|
// right
|
||||||
|
olenr = olen / 2;
|
||||||
|
edrain = (effDrainFunc*)(efftab[e].h->drain);
|
||||||
|
(*edrain)(&efftabR[e], obufr, &olenr);
|
||||||
|
obuf = efftab[e].obuf;
|
||||||
|
// this loop implies left and right effect will always output the same
|
||||||
|
// amount of data
|
||||||
|
for (i=0; i<olenr; ++i) {
|
||||||
|
*obuf++ = obufl[i];
|
||||||
|
*obuf++ = obufr[i];
|
||||||
|
}
|
||||||
|
efftab[e].olen = olenl + olenr;
|
||||||
|
}
|
||||||
|
return (efftab[e].olen);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int formatSReadFunc(STREAM_TYPE*);
|
||||||
|
typedef LONG formatReadFunc(STREAM_TYPE*, LONG*, LONG);
|
||||||
|
typedef int formatStopReadFunc(STREAM_TYPE*);
|
||||||
|
typedef void effStartFunc(EFFECTS_TYPE*);
|
||||||
|
typedef void effStopFunc(EFFECTS_TYPE*);
|
||||||
|
|
||||||
|
static void read_file(Filename filename, byte** buf, unsigned long& slen) {
|
||||||
int e, havedata;
|
int e, havedata;
|
||||||
ostringstream out;
|
ostringstream out;
|
||||||
|
formatSReadFunc* srfunc;
|
||||||
|
formatReadFunc* rfunc;
|
||||||
|
formatStopReadFunc* strfunc;
|
||||||
|
effStartFunc* esfunc;
|
||||||
|
effStopFunc* estfunc;
|
||||||
|
|
||||||
init_stream();
|
init_stream();
|
||||||
if ((informat.fp = fopen(filename.c_str(), READBINARY)) == NULL) {
|
if ((iformat.fp = fopen(filename.c_str(), READBINARY)) == NULL) {
|
||||||
audio_cat->error() << "could not open '" << filename << "'" << endl;
|
audio_cat->error() << "could not open '" << filename << "'" << endl;
|
||||||
return (byte*)0L;
|
*buf = (byte*)0L;
|
||||||
|
slen = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
informat.filname = filename.c_str();
|
iformat.filename = (char*)filename.c_str();
|
||||||
informat.filetype = filename.get_extension();
|
iformat.filetype = (char*)filename.get_extension().c_str();
|
||||||
informat.comment = filename.c_str(); // for lack of anything better
|
iformat.comment = (char*)filename.c_str(); // for lack of anything better
|
||||||
// now we start some more real work
|
// now we start some more real work
|
||||||
GETTYPE(&informat);
|
GETTYPE(&iformat);
|
||||||
// read and write starters can change their formats
|
// read and write starters can change their formats
|
||||||
if ((*informat.h->startread)(&informat) == COMPAT_EOF) {
|
srfunc = (formatSReadFunc*)(iformat.h->startread);
|
||||||
|
if ((*srfunc)(&iformat) == COMPAT_EOF) {
|
||||||
audio_cat->error() << "failed to start read" << endl;
|
audio_cat->error() << "failed to start read" << endl;
|
||||||
return (byte*)0L;
|
*buf = (byte*)0L;
|
||||||
|
slen = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
CHECKFORMAT(&informat);
|
CHECKFORMAT(&iformat);
|
||||||
if (audio_cat->is_debug())
|
if (audio_cat->is_debug())
|
||||||
audio_cat->debug() << "Input file '" << informat.filename
|
audio_cat->debug() << "Input file '" << iformat.filename
|
||||||
<< "': sample rate = " << informat.info.rate
|
<< "': sample rate = " << iformat.info.rate
|
||||||
<< " size = " << SIZES[informat.info.size]
|
<< " size = " << SIZES[iformat.info.size]
|
||||||
<< " encoding = " << ENCODING[informat.info.encoding]
|
<< " encoding = " << ENCODING[iformat.info.ENCODEFIELD]
|
||||||
<< " " << informat.info.channels
|
<< " " << iformat.info.channels
|
||||||
<< (informat.info.channels > 1)?"channels":"channel"
|
<< ((iformat.info.channels > 1)?"channels":"channel")
|
||||||
<< endl;
|
<< endl;
|
||||||
if (audio_cat->is_debug())
|
if (audio_cat->is_debug())
|
||||||
audio_cat->debug() << "Input file comment: '" << informat.comment << "'"
|
audio_cat->debug() << "Input file comment: '" << iformat.comment << "'"
|
||||||
<< endl;
|
<< endl;
|
||||||
COPYFORMAT(&informat, &outformat);
|
COPYFORMAT(&iformat, &oformat);
|
||||||
check_effects();
|
check_effects();
|
||||||
// start all effects
|
// start all effects
|
||||||
for (e=1; e<neffects; ++e) {
|
for (e=1; e<neffects; ++e) {
|
||||||
(*efftab[e].h->start)(&efftab[e]);
|
esfunc = (effStartFunc*)(efftab[e].h->start);
|
||||||
if (efftabR[e].name)
|
(*esfunc)(&efftab[e]);
|
||||||
(*efftabR[e].h->start)(&efftabR[e]);
|
if (efftabR[e].name) {
|
||||||
|
esfunc = (effStartFunc*)(efftabR[e].h->start);
|
||||||
|
(*esfunc)(&efftabR[e]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// reserve output buffers for all effects
|
// reserve output buffers for all effects
|
||||||
for (e=0; e<neffects; e++) {
|
for (e=0; e<neffects; e++) {
|
||||||
@ -147,8 +290,8 @@ static byte* read_file(Filename filename) {
|
|||||||
efftabR[e].obuf = new LONG[BUFSIZ*sizeof(LONG)];
|
efftabR[e].obuf = new LONG[BUFSIZ*sizeof(LONG)];
|
||||||
}
|
}
|
||||||
// get the main while loop ready, have some data for it to start on
|
// get the main while loop ready, have some data for it to start on
|
||||||
efftab[0].olen = (*informat.h->read)(&informat, efftab[0].obuf,
|
rfunc = (formatReadFunc*)(iformat.h->read);
|
||||||
(LONG)BUFSIZ);
|
efftab[0].olen = (*rfunc)(&iformat, efftab[0].obuf, (LONG)BUFSIZ);
|
||||||
efftab[0].odone = 0;
|
efftab[0].odone = 0;
|
||||||
// run input data thru effects and get more until olen == 0
|
// run input data thru effects and get more until olen == 0
|
||||||
while (efftab[0].olen > 0) {
|
while (efftab[0].olen > 0) {
|
||||||
@ -167,7 +310,7 @@ static byte* read_file(Filename filename) {
|
|||||||
for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
|
for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
|
||||||
LONG foo = efftab[neffects-1].obuf[i];
|
LONG foo = efftab[neffects-1].obuf[i];
|
||||||
signed short bar = (foo >> 16);
|
signed short bar = (foo >> 16);
|
||||||
unsigned char *b = &bar;
|
unsigned char *b = (unsigned char*)&bar;
|
||||||
out << *b << *(++b);
|
out << *b << *(++b);
|
||||||
}
|
}
|
||||||
efftab[neffects-1].odone = efftab[neffects-1].olen;
|
efftab[neffects-1].odone = efftab[neffects-1].olen;
|
||||||
@ -181,8 +324,8 @@ static byte* read_file(Filename filename) {
|
|||||||
}
|
}
|
||||||
} while (havedata);
|
} while (havedata);
|
||||||
// read another chunk
|
// read another chunk
|
||||||
efftab[0].olen = (*informat.h->read)(&informat, efftab[0].obuf,
|
rfunc = (formatReadFunc*)(iformat.h->read);
|
||||||
(LONG)BUFSIZ);
|
efftab[0].olen = (*rfunc)(&iformat, efftab[0].obuf, (LONG)BUFSIZ);
|
||||||
efftab[0].odone = 0;
|
efftab[0].odone = 0;
|
||||||
}
|
}
|
||||||
// drain the effects out first to last. push the residue thru subsequent
|
// drain the effects out first to last. push the residue thru subsequent
|
||||||
@ -195,7 +338,7 @@ static byte* read_file(Filename filename) {
|
|||||||
for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
|
for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
|
||||||
LONG foo = efftab[neffects-1].obuf[i];
|
LONG foo = efftab[neffects-1].obuf[i];
|
||||||
signed short bar = (foo >> 16);
|
signed short bar = (foo >> 16);
|
||||||
unsigned char *b = &bar;
|
unsigned char *b = (unsigned char*)&bar;
|
||||||
out << *b << *(++b);
|
out << *b << *(++b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,23 +347,36 @@ static byte* read_file(Filename filename) {
|
|||||||
}
|
}
|
||||||
// stop all effects. In so doing, some may generate more data
|
// stop all effects. In so doing, some may generate more data
|
||||||
for (e=1; e<neffects; ++e) {
|
for (e=1; e<neffects; ++e) {
|
||||||
(*efftab[e].h->stop)(&efftab[e]);
|
estfunc = (effStopFunc*)(efftab[e].h->stop);
|
||||||
if (efftabR[e].name)
|
(*estfunc)(&efftab[e]);
|
||||||
(*efftabR[e].h->stop)(&efftabR[e]);
|
if (efftabR[e].name) {
|
||||||
|
estfunc = (effStopFunc*)(efftabR[e].h->stop);
|
||||||
|
(*estfunc)(&efftabR[e]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// stop reading the file
|
// stop reading the file
|
||||||
if ((*informat.h->stopread)(&informat) == COMPAT_EOF) {
|
strfunc = (formatStopReadFunc*)(iformat.h->stopread);
|
||||||
|
if ((*strfunc)(&iformat) == COMPAT_EOF) {
|
||||||
audio_cat->error() << "error stoping input file" << endl;
|
audio_cat->error() << "error stoping input file" << endl;
|
||||||
}
|
}
|
||||||
fclose(informat.fp);
|
fclose(iformat.fp);
|
||||||
// generate output
|
// generate output
|
||||||
string s = out.str();
|
string s = out.str();
|
||||||
int slen = s.length();
|
slen = s.length();
|
||||||
byte* ret = new byte[slen];
|
*buf = new byte[slen];
|
||||||
memcpy(ret, s.data(), slen);
|
memcpy(*buf, s.data(), slen);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void cleanup(void) {
|
||||||
|
// make sure everything is shut down
|
||||||
|
if (iformat.fp)
|
||||||
|
fclose(iformat.fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SOXST */
|
||||||
|
|
||||||
#ifdef AUDIO_USE_MIKMOD
|
#ifdef AUDIO_USE_MIKMOD
|
||||||
|
|
||||||
void AudioDestroySt(AudioTraits::SampleClass* sample) {
|
void AudioDestroySt(AudioTraits::SampleClass* sample) {
|
||||||
@ -259,18 +415,23 @@ void AudioLoadSt(AudioTraits::SampleClass** sample,
|
|||||||
|
|
||||||
#ifdef AUDIO_USE_LINUX
|
#ifdef AUDIO_USE_LINUX
|
||||||
|
|
||||||
|
#include "audio_linux_traits.h"
|
||||||
|
|
||||||
void AudioDestroySt(AudioTraits::SampleClass* sample) {
|
void AudioDestroySt(AudioTraits::SampleClass* sample) {
|
||||||
delete sample;
|
delete sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLoadSt(AudioTraits::SampleClass** sample,
|
void AudioLoadSt(AudioTraits::SampleClass** sample,
|
||||||
AudioTraits::PlayerClass** player,
|
AudioTraits::PlayerClass** player,
|
||||||
AudioTraits::DeleteSampleFunc** destroy, Filename) {
|
AudioTraits::DeleteSampleFunc** destroy, Filename filename) {
|
||||||
audio_cat->warning() << "linux doesn't support reading raw data yet"
|
byte* buf;
|
||||||
<< endl;
|
unsigned long len;
|
||||||
*sample = (AudioTraits::SampleClass*)0L;
|
read_file(filename, &buf, len);
|
||||||
*player = (AudioTraits::PlayerClass*)0L;
|
if (buf != (byte*)0L) {
|
||||||
*destroy = AudioDestroySt;
|
*sample = LinuxSample::load_raw(buf, len);
|
||||||
|
*player = LinuxPlayer::get_instance();
|
||||||
|
*destroy = AudioDestroySt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* AUDIO_USE_LINUX */
|
#else /* AUDIO_USE_LINUX */
|
||||||
@ -302,6 +463,7 @@ void AudioLoadSt(AudioTraits::SampleClass** sample,
|
|||||||
#endif /* AUDIO_USE_MIKMOD */
|
#endif /* AUDIO_USE_MIKMOD */
|
||||||
|
|
||||||
ConfigureFn(audio_load_st) {
|
ConfigureFn(audio_load_st) {
|
||||||
|
#ifdef HAVE_SOXST
|
||||||
for (int i=0; FORMATS[i].names != (char**)0L; ++i)
|
for (int i=0; FORMATS[i].names != (char**)0L; ++i)
|
||||||
for (int j=0; FORMATS[i].names[j] != (char*)0L; ++j) {
|
for (int j=0; FORMATS[i].names[j] != (char*)0L; ++j) {
|
||||||
if (audio_cat->is_debug())
|
if (audio_cat->is_debug())
|
||||||
@ -309,4 +471,5 @@ ConfigureFn(audio_load_st) {
|
|||||||
<< "'" << endl;
|
<< "'" << endl;
|
||||||
AudioPool::register_sample_loader(FORMATS[i].names[j], AudioLoadSt);
|
AudioPool::register_sample_loader(FORMATS[i].names[j], AudioLoadSt);
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_SOXST */
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ void AudioLoadWav(AudioTraits::SampleClass** sample,
|
|||||||
AudioTraits::PlayerClass** player,
|
AudioTraits::PlayerClass** player,
|
||||||
AudioTraits::DeleteSampleFunc** destroy, Filename) {
|
AudioTraits::DeleteSampleFunc** destroy, Filename) {
|
||||||
*sample = (AudioTraits::SampleClass*)0L;
|
*sample = (AudioTraits::SampleClass*)0L;
|
||||||
*player = (audioTraits::PlayerClass*)0L;
|
*player = (AudioTraits::PlayerClass*)0L;
|
||||||
*destroy = AudioDestroyWav;
|
*destroy = AudioDestroyWav;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,15 +55,11 @@ public:
|
|||||||
#ifdef PENV_WIN32
|
#ifdef PENV_WIN32
|
||||||
#define AUDIO_USE_WIN32
|
#define AUDIO_USE_WIN32
|
||||||
#else /* PENV_WIN32 */
|
#else /* PENV_WIN32 */
|
||||||
/*
|
|
||||||
#ifdef PENV_LINUX
|
#ifdef PENV_LINUX
|
||||||
#define AUDIO_USE_LINUX
|
#define AUDIO_USE_LINUX
|
||||||
#else /* PENV_LINUX *
|
#else /* PENV_LINUX */
|
||||||
*/
|
|
||||||
#define AUDIO_USE_NULL
|
#define AUDIO_USE_NULL
|
||||||
/*
|
#endif /* PENV_LINUX */
|
||||||
#endif /* PENV_LINUX *
|
|
||||||
*/
|
|
||||||
#endif /* PENV_WIN32 */
|
#endif /* PENV_WIN32 */
|
||||||
#endif /* HAVE_MIKMOD */
|
#endif /* HAVE_MIKMOD */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user