summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaromil <jaromil@949728d9-16ea-0310-a75c-cbdf8430a4b8>2006-10-18 14:46:58 (GMT)
committer jaromil <jaromil@949728d9-16ea-0310-a75c-cbdf8430a4b8>2006-10-18 14:46:58 (GMT)
commit32d692890c5a3dd1ac61ce52ba59b03e7c6c3b1c (patch)
treed6e147b623c71974f9ecb25749b9ab4b8238bc88
parent6afad8245aed016f5f41dedc177993eb92209bf0 (diff)
sound playback
git-svn-id: svn://dyne.org/montevideo/ivysync@73 949728d9-16ea-0310-a75c-cbdf8430a4b8
-rw-r--r--branches/lydia/Makefile10
-rw-r--r--branches/lydia/sndfile_decoder.cpp (renamed from branches/lydia/dec_snd.cpp)27
-rw-r--r--branches/lydia/sndfile_decoder.h (renamed from branches/lydia/dec_snd.h)7
-rw-r--r--branches/lydia/sound_decoder.cpp19
-rw-r--r--branches/lydia/sound_decoder.h162
-rw-r--r--branches/lydia/sound_device.cpp (renamed from branches/lydia/dev_sound.cpp)134
-rw-r--r--branches/lydia/sound_device.h (renamed from branches/lydia/dev_sound.h)23
-rw-r--r--branches/lydia/xmlrpc.h7
8 files changed, 227 insertions, 162 deletions
diff --git a/branches/lydia/Makefile b/branches/lydia/Makefile
index a81cdd5..03a5930 100644
--- a/branches/lydia/Makefile
+++ b/branches/lydia/Makefile
@@ -10,19 +10,21 @@ LINKER = ld
GTKFLAGS = `pkg-config --cflags gtk+-2.0`
GTKLIBS = `pkg-config --libs gtk+-2.0`
+SNDLIBS = `pkg-config --libs sndfile`
# debugging flags:
-CPPFLAGS = -I. -Ixmlrpc++ -Wall -g -ggdb $(GTKFLAGS) $(AOFLAGS)
+CPPFLAGS = -I. -Ixmlrpc++ -Iportaudio -Wall -g -ggdb $(GTKFLAGS) $(AOFLAGS)
# optimized flags:
#CPPFLAGS = -I. -Ixmlrpc++ -Wall -O2 -fomit-frame-pointer -ffast-math $(GTKFLAGS)
-LIBS = xmlrpc++/libxmlrpc++.a -lpthread -lssl
+LIBS = xmlrpc++/libxmlrpc++.a portaudio/libportaudio.a -lpthread -lssl
-IVYSYNC_OBJ = decoder.o thread.o linklist.o utils.o cmdline.o gui.o xmlrpc.o
+IVYSYNC_OBJ = decoder.o thread.o linklist.o utils.o cmdline.o gui.o \
+ pipe.o xmlrpc.o sound_device.o sndfile_decoder.o sound_decoder.o
all: xmlrpc ivysync
@@ -30,7 +32,7 @@ xmlrpc:
cd xmlrpc++ && $(MAKE)
ivysync: $(IVYSYNC_OBJ)
- $(CPP) $(CPPFLAGS) -o ivysync $(IVYSYNC_OBJ) $(LIBS) $(GTKLIBS)
+ $(CPP) $(CPPFLAGS) -o ivysync $(IVYSYNC_OBJ) $(LIBS) $(GTKLIBS) $(SNDLIBS)
#make clean
clean:
diff --git a/branches/lydia/dec_snd.cpp b/branches/lydia/sndfile_decoder.cpp
index f856c68..499a890 100644
--- a/branches/lydia/dec_snd.cpp
+++ b/branches/lydia/sndfile_decoder.cpp
@@ -18,23 +18,21 @@
*
*/
+#include <string.h>
-#include <dec_snd.h>
-#include <jutils.h>
-#include <config.h>
-
-#ifdef HAVE_SNDFILE
+#include <sndfile_decoder.h>
+#include <utils.h>
/* ----- LibSndFile input channel ----- */
MuseDecSndFile::MuseDecSndFile ():MuseDec (){
- func ("MuseDecSndFile::MuseDecSndFile()");
+ D("MuseDecSndFile::MuseDecSndFile()");
strncpy (name, "Snd", 4);
memset(&sf_info_struct, 0, sizeof(sf_info_struct));
}
MuseDecSndFile::~MuseDecSndFile (){
- func ("MuseDecSndFile::~MuseSndFile()");
+ D ("MuseDecSndFile::~MuseSndFile()");
sf_close (sf);
}
@@ -48,7 +46,7 @@ int MuseDecSndFile::load (char *file) {
/* all the info about the audio file into the sf_info_struct struct */
if(!(sf = sf_open(file, SFM_READ, &sf_info_struct))) {
- warning("MuseDecSndFile:_load(): cannot open input file");
+ W("MuseDecSndFile:_load(): cannot open input file");
return (0);
}
/*
@@ -67,14 +65,14 @@ int MuseDecSndFile::load (char *file) {
channels = sf_info_struct.channels;
seekable = sf_info_struct.seekable ? true : false;
- func("Opened audio file: samplerate => %d, channels => %d, seekable => %s",
+ D("Opened audio file: samplerate => %d, channels => %d, seekable => %s",
samplerate, channels, seekable ? "true" : "false");
framepos = 0;
if(seekable) {
frametot = sf_info_struct.frames;
- func("Audio file is seekable: total frames: %d", frametot);
+ D("Audio file is seekable: total frames: %d", frametot);
res = 1;
}
else res = 2;
@@ -91,7 +89,7 @@ IN_DATATYPE *MuseDecSndFile::get_audio () {
framepos += frames/channels;
fps = samplerate;
- // func("MuseDecSndFile::get_audio => Frames readed: %d/%d", framepos, frametot);
+ // D("MuseDecSndFile::get_audio => Frames readed: %d/%d", framepos, frametot);
return ((IN_DATATYPE *) snd_buffer);
} else { framepos=0; eos = true; return (NULL); }
@@ -103,19 +101,18 @@ bool MuseDecSndFile::seek (float pos) {
framepos = 0;
sf_seek(sf, 0, SEEK_SET);
- func("MuseDecSndFile::seek => Stop. Return to the begin of the track");
+ D("MuseDecSndFile::seek => Stop. Return to the begin of the track");
} else {
if((framepos = sf_seek(sf, (sf_count_t)(frametot * pos), SEEK_SET))==-1) {
- func("MuseDecSndFile::seek error"); //,sf_strerror(sf));
+ D("MuseDecSndFile::seek error"); //,sf_strerror(sf));
return false;
}
- func("MuseDecSndFile::seek at position %d/%d", framepos, frametot);
+ D("MuseDecSndFile::seek at position %d/%d", framepos, frametot);
}
return true;
}
-#endif /* HAVE SNDFILE */
diff --git a/branches/lydia/dec_snd.h b/branches/lydia/sndfile_decoder.h
index 7359baf..0d9cd25 100644
--- a/branches/lydia/dec_snd.h
+++ b/branches/lydia/sndfile_decoder.h
@@ -25,11 +25,7 @@
#ifndef __IN_SND_H__
#define __IN_SND_H__
-#include <config.h>
-
-#ifdef HAVE_SNDFILE
-
-#include <decoder.h>
+#include <sound_decoder.h>
/* libsndfile inclusion */
#include <sndfile.h>
@@ -60,5 +56,4 @@ class MuseDecSndFile:public MuseDec
};
-#endif /* HAVE SNDFILE */
#endif
diff --git a/branches/lydia/sound_decoder.cpp b/branches/lydia/sound_decoder.cpp
new file mode 100644
index 0000000..825a51b
--- /dev/null
+++ b/branches/lydia/sound_decoder.cpp
@@ -0,0 +1,19 @@
+
+// "$Id: decoder.cpp 328 2004-02-13 16:58:16Z jaromil $"
+
+#include <sound_decoder.h>
+#include <utils.h>
+
+MuseDec::MuseDec() {
+ bitrate = samplerate = channels = frames = 0;
+ seekable = false; err = false; eos = false;
+ if(pthread_mutex_init (&mutex,NULL) == -1)
+ E("%i:%s error initializing POSIX thread mutex",
+ __LINE__,__FILE__);
+}
+
+MuseDec::~MuseDec() {
+ if(pthread_mutex_destroy(&mutex) == -1)
+ E("error destroying POSIX thread mutex",
+ __LINE__,__FILE__);
+}
diff --git a/branches/lydia/sound_decoder.h b/branches/lydia/sound_decoder.h
new file mode 100644
index 0000000..b493f50
--- /dev/null
+++ b/branches/lydia/sound_decoder.h
@@ -0,0 +1,162 @@
+/* MuSE - Multiple Streaming Engine
+ * Copyright (C) 2000-2004 Denis Rojo aka jaromil <jaromil@dyne.org>
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code 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.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+
+ $Id: decoder.h 408 2004-12-13 00:26:37Z jaromil $"
+
+*/
+
+/**
+ @file decoder.h MuSE decoder abstraction
+ @desc header file to be included by decoder implementations
+*/
+
+#ifndef __DECODER_H__
+#define __DECODER_H__
+
+#include <pthread.h>
+#include <inttypes.h>
+
+#define IN_DATATYPE int16_t
+#define MIX_CHUNK 1152 //2048
+#define IN_CHUNK MIX_CHUNK
+#define IN_PIPESIZE IN_CHUNK*(sizeof(IN_DATATYPE))*64
+
+/**
+ This class should be inherited by every decoder implementation:
+ it is the decoder parent class giving some common functionalities
+ to its childs.
+
+ Most important thing for making decoders is to implement the pure
+ virtual functions of this class, inheriting all the rest.
+ The pure virtual functions to be carefully implemented in a decoder are:
+ - MuseDec::load
+ - the destructor class for closing
+ - MuseDec::seek
+ - MuseDec::get_audio
+ Then the decoder must also take care to set properly the following
+ variables inside the load function:
+ - MuseDec::samplerate
+ - MuseDec::channels
+ - MuseDec::bitrate
+ - MuseDec::frametot
+ - MuseDec::seekable
+ And the following variables in the get_audio function:
+ - MuseDec::frames
+ - MuseDec::fps
+ - MuseDec::eos
+ - MuseDec::err
+
+ For example decoder implementations, please refer to:
+ - MuseDecMp3 class implemented in dec_mp3.h and dec_mp3.cpp
+ - MuseDecOgg class implemented in dec_ogg.h and dec_ogg.cpp
+ - MuseDecSnd class implemented in dec_snd.h and dec_snd.cpp
+
+ @brief decoder parent abstraction class
+*/
+
+class MuseDec {
+
+ public:
+
+ /**
+ The decoder implementations inheriting from this class can
+ use their constructor to initialize their variables and to
+ fill up the MuseDec::name buffer with their identification.
+
+ @brief decoder parent class constructor */
+ MuseDec();
+
+ /**
+
+ A decoder implementation should take care to close all files and
+ free all buffers in the destructor.
+
+ @brief decoder parent class destructor */
+ virtual ~MuseDec();
+
+ /**
+ Open up a filename (full path) and makes it ready for decoding,
+ the filename or url can be formed in different ways, depending
+ on the decoder implementation.
+
+ This is a pure virtual function: needs to be implemented in decoders.
+
+ @brief open file in decoder
+ @param file full pathname for file, or url accepted by the decoder
+ @return 0 on error, otherwise
+ - 1 = success, channel is seekable
+ - 2 = success, channel is not seekable
+ */
+ virtual int load(char *file) = 0; /* open filename */
+
+ /**
+ Seek position over the audio data available to an opened channel.
+
+ This operation is only possible if the channel is seekable (see the
+ flag in this class and the return code of MuseDec::load).
+
+ This is a pure virtual function: needs to be implemented in decoders.
+
+ @brief seek to a position
+ @param pos floating point value from 0.0 to 1.0
+ @return true on success, false otherwise */
+ virtual bool seek(float pos) = 0; /* seek to position from 0.0 1.0 */
+
+ /**
+ Decode another chunk of audio for the channel at the current position,
+ this function is implementing the low-level decoder functionalities
+ to obtain the audio pcm to be mixed.
+
+ The audio will be then resampled at a common rate and mixed by MuSE.
+
+ This is a pure virtual function: needs to be implemented in decoders.
+
+ @brief decode a chunk of channel audio
+ @return pointer to decoded pcm buffer */
+ virtual IN_DATATYPE *get_audio() = 0; /* decode audio */
+
+ char name[5]; ///< decoder short name (3 letters)
+
+ /**
+ * the following variables describe the audio returned by
+ * MuseDec::get_audio and must be setted up by the decoder implementation.
+ */
+ int samplerate; ///< samplerate of audio decoded
+ int channels; ///< number of audio channels decoded
+ int bitrate; ///< bitrate of the compressed audio being decoded
+ int frames; ///< quantity of audio frames (16bit words) decoded
+ int framepos; ///< position offset on the frames
+ int frametot; ///< total frames in opened audio (if seekable, othwrwise 0)
+ int fps; ///< samplerate / frames quantity
+ bool seekable; ///< true if the channel audio is seekable
+ bool eos; ///< true on end of stream reached
+ bool err; ///< true when an error occurred during audio decoding
+ ///////////////////////////////////////////////////////////
+
+ /* pthread stuff */
+ void lock() { pthread_mutex_lock(&mutex); };
+ ///< lock decoder thread
+ void unlock() { pthread_mutex_unlock(&mutex); };
+ ///< unlock decoder thread
+
+ private:
+ pthread_mutex_t mutex;
+
+};
+
+#endif
diff --git a/branches/lydia/dev_sound.cpp b/branches/lydia/sound_device.cpp
index 8c33d40..b3373ca 100644
--- a/branches/lydia/dev_sound.cpp
+++ b/branches/lydia/sound_device.cpp
@@ -21,11 +21,17 @@
*/
#include <stdlib.h>
-#include <config.h>
-#include <dev_sound.h>
-#include <jutils.h>
-#include <generic.h>
+#include <sound_device.h>
+#include <utils.h>
+
+/* settings (take care!) */
+#define IN_DATATYPE int16_t
+#define OUT_DATATYPE int16_t
+#define MIX_CHUNK 1152 //2048
+#define IN_CHUNK MIX_CHUNK
+#define IN_PIPESIZE IN_CHUNK*(sizeof(IN_DATATYPE))*64
+#define SAMPLE_RATE 44100 // 44100
#define PA_SAMPLE_TYPE paFloat32
#define PA_SAMPLES_PER_FRAME 2
@@ -37,41 +43,6 @@
#define OUTPUT_DEVICE Pa_GetDefaultOutputDeviceID()
-#ifdef HAVE_JACK
-int dev_jack_process(jack_nframes_t nframes, void *arg) {
-
- jack_nframes_t opframes;
- SoundDevice *dev = (SoundDevice*)arg;
- if(!dev->jack) return 0; // just return
-
- // take output from pipe and send it to jack
- dev->jack_out_buf = (jack_default_audio_sample_t*)
- jack_port_get_buffer(dev->jack_out_port,nframes);
- opframes = dev->jack_out_pipe->read
- (nframes * sizeof(float) * 2 , dev->jack_out_buf);
-
- // take input from jack and send it in pipe
- dev->jack_in_buf = (jack_default_audio_sample_t*)
- jack_port_get_buffer(dev->jack_in_port,nframes);
- dev->jack_in_pipe->write // does the float2int conversion in one pass
- (nframes * sizeof(float) * 2 , dev->jack_in_buf);
-
- return 0;
-}
-
-void dev_jack_shutdown(void *arg) {
- SoundDevice *dev = (SoundDevice*)arg;
- // close the jack channels
- dev->jack = false;
- jack_port_unregister(dev->jack_client, dev->jack_in_port);
- jack_port_unregister(dev->jack_client, dev->jack_out_port);
- jack_deactivate(dev->jack_client);
- delete dev->jack_in_pipe;
- delete dev->jack_out_pipe;
-}
-#endif
-
-
SoundDevice::SoundDevice() {
memset(&input_device,0,sizeof(input_device));
memset(&output_device,0,sizeof(output_device));
@@ -83,9 +54,6 @@ SoundDevice::SoundDevice() {
output_device.pipe->set_block(true,false);
input_device.pipe->set_output_type("copy_float_to_int16");
output_device.pipe->set_input_type("copy_int16_to_float");
- jack = false;
- jack_in = false;
- jack_out = false;
}
SoundDevice::~SoundDevice() {
@@ -144,7 +112,6 @@ long len = framesPerBuffer * (PA_SAMPLES_PER_FRAME*sizeof(PA_SAMPLE_TYPE));
bool SoundDevice::input(bool state) {
bool res = false;
- if(jack) return true;
if(!res) res = pa_open(state,PaInput);
return res;
}
@@ -198,9 +165,9 @@ bool SoundDevice::pa_open(bool state,int mode) {
}
if(state && ((pa_mode & creq) != creq)) {
dev->info = (PaDeviceInfo*)Pa_GetDeviceInfo( dev->id );
- if(dev->info) notice("Opening %s device: %s",dir,dev->info->name);
+ if(dev->info) N("Opening %s device: %s",dir,dev->info->name);
else {
- error("%s device not available",dir);
+ E("%s device not available",dir);
return false;
}
if((pa_mode & oreq) == oreq) {
@@ -212,7 +179,7 @@ bool SoundDevice::pa_open(bool state,int mode) {
if(err == paNoError ) output_device.stream = input_device.stream;
}
else {
- error("Full duplex has been requested but we don't have portaudio information");
+ E("Full duplex has been requested but we don't have portaudio information");
return false;
}
}
@@ -221,19 +188,19 @@ bool SoundDevice::pa_open(bool state,int mode) {
}
if( err != paNoError) {
Pa_Terminate();
- error("error opening %s sound device: %s",dir,Pa_GetErrorText( err ) );
+ E("error opening %s sound device: %s",dir,Pa_GetErrorText( err ) );
return false;
}
else {
err = Pa_StartStream(dev->stream);
if(err != paNoError) {
- error("error starting %s audio stream: %s",dir,Pa_GetErrorText( err ) );
+ E("error starting %s audio stream: %s",dir,Pa_GetErrorText( err ) );
return false;
}
pa_mode = pa_mode | creq;
}
} else if(!state && dev->stream) { // XXX - i have to check if this is still right
- if(dev->info) notice("Closing %s device: %s",dir,dev->info->name);
+ if(dev->info) N("Closing %s device: %s",dir,dev->info->name);
if((pa_mode & creq) == creq) {
if((pa_mode & oreq) == oreq) {
pa_mode = oreq;
@@ -254,53 +221,17 @@ bool SoundDevice::pa_open(bool state,int mode) {
bool SoundDevice::output(bool state) {
bool res = false;
- if(jack) return true;
if(!res) res = pa_open(state,PaOutput);
return res;
}
bool SoundDevice::open(bool read, bool write) {
- // notice("detecting sound device");
+ N("open sound device");
-#ifdef HAVE_JACK
- // we try to open up a jack client
- jack_sample_size = sizeof(jack_default_audio_sample_t);
- if(!jack) // check if it is not allready on
- if( (jack_client = jack_client_new("MuSE")) !=0 ) {
- notice("jack audio daemon detected");
- act("hooking in/out sound channels");
- warning("this feature is still experimental and won't work!");
- warning("you need to stop jack and free the audio card");
- jack = true;
- jack_samplerate = jack_get_sample_rate(jack_client);
- jack_set_process_callback(jack_client, dev_jack_process, this);
- jack_on_shutdown(jack_client,dev_jack_shutdown,this);
-
- jack_in_pipe = new Pipe();
- jack_in_pipe->set_output_type("copy_float_to_int16");
- jack_in_pipe->set_block(false,true);
-
- jack_out_pipe = new Pipe();
- jack_out_pipe->set_input_type("copy_int16_to_float");
- jack_in_pipe->set_block(true,false);
-
- // open the jack input channel
- jack_in_port = jack_port_register(jack_client, "capture",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsInput, 0);
- // open the jack output channel
- jack_out_port = jack_port_register(jack_client, "playback",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput, 0);
-
- jack_activate(jack_client);
- return true;
- }
-#endif
if( ! output(write) ) return false;
- //if( ! input(read) ) return false;
+ if( ! input(read) ) return false;
return true;
}
@@ -340,15 +271,9 @@ int SoundDevice::read(void *buf, int len) {
// len is in samples: 4*2 32bit stereo
int res = -1;
- if(jack) {
-
- res = jack_in_pipe->read(len*2,buf);
-
- } else if(input_device.stream) { // portaudio
+ // takes number of left and right frames (stereo / 2)
+ res = input_device.pipe->read(len*2,buf);
- // takes number of left and right frames (stereo / 2)
- res = input_device.pipe->read(len*2,buf);
- }
return res;
}
@@ -356,28 +281,15 @@ int SoundDevice::write(void *buf, int len) {
// len is in samples, for bytes must *2 (16bit)
int res = -1;
- if(jack) { // jack audio daemon
+ res = output_device.pipe->write(len,buf);
+ //func("dspout available pipe space: %d \n",output_device.pipe->space());
- res = jack_out_pipe->write(len*2,buf);
-
- } else if(output_device.stream) { // portaudio
- res = output_device.pipe->write(len,buf);
- //func("dspout available pipe space: %d \n",output_device.pipe->space());
- }
return res;
}
void SoundDevice::flush_output() {
- if(jack)
- jack_out_pipe->flush();
- else if(output_device.stream) { // portaudio
- output_device.pipe->flush();
- }
+ output_device.pipe->flush();
}
void SoundDevice::flush_input() {
- if(jack)
- jack_in_pipe->flush();
- else if(input_device.stream) {
input_device.pipe->flush();
- }
}
diff --git a/branches/lydia/dev_sound.h b/branches/lydia/sound_device.h
index c2480f1..71e232a 100644
--- a/branches/lydia/dev_sound.h
+++ b/branches/lydia/sound_device.h
@@ -1,15 +1,7 @@
#ifndef __DEV_SOUND_H__
#define __DEV_SOUND_H__
-#include <config.h>
-
-#ifdef HAVE_JACK
-#include <jack/jack.h>
-#endif
-
-//#ifdef HAVE_PORTAUDIO
#include <portaudio.h>
-//#endif
#include <pipe.h>
@@ -56,10 +48,6 @@ class SoundDevice {
void flush_input();
void flush_output();
- bool jack;
- bool jack_in;
- bool jack_out;
-
/* TODO - should be private */
PaDevInfo input_device; ///< portaudio input device
PaDevInfo output_device; ///< portaudio output device
@@ -75,17 +63,6 @@ class SoundDevice {
#define PaInput 1
#define PaOutput 2
- Pipe *jack_in_pipe;
- Pipe *jack_out_pipe;
-#ifdef HAVE_JACK
- jack_client_t *jack_client;
- jack_port_t *jack_in_port;
- jack_port_t *jack_out_port;
- jack_default_audio_sample_t *jack_in_buf;
- jack_default_audio_sample_t *jack_out_buf;
- size_t jack_sample_size;
- int jack_samplerate;
-#endif
};
diff --git a/branches/lydia/xmlrpc.h b/branches/lydia/xmlrpc.h
index 912847d..55f4d7d 100644
--- a/branches/lydia/xmlrpc.h
+++ b/branches/lydia/xmlrpc.h
@@ -28,13 +28,14 @@
#include <stdlib.h>
#include <thread.h>
+#include <linklist.h>
using namespace XmlRpc;
// damn STL
-#include <vector>
-using namespace std;
-using namespace __gnu_cxx;
+//#include <vector>
+//using namespace std;
+//using namespace __gnu_cxx;
// METHODS: