Commit f8cdc96f authored by yanmorin's avatar yanmorin

Audio refactoring to use float or integer with portaudio.

Samplerate is now a dependancy.
parent 10461835
2006-08-30 Yan Morin
* Set libsamplerate as a dependency
* Refactoring samplerate conversion, -DDATAFORMAT_IS_FLOAT allow the user to use float instead of int
2006-08-02 Yan Morin
* Add IAX quelch/unquelch
......
......@@ -80,11 +80,14 @@ Building the dependencies
-------------------------
If you do not use either the development packages of your distribution or the source packages made by the upstream authors of dependencies, you may want to try our custom dependencies building script in tools/ directory:
Note that commoncpp, ccrtp, libosip and libexosip, samplerate are in debian and fedora.
1. cd tools/
2. edit config.sh to change the default prefix (/usr/local)
3. ./download.sh
4. ./install.sh
5. ./portaudio.sh <-- compile portaudio
2. ./portaudio.sh <-- compile portaudio
3. if you want to install other software, check inside the file config.sh
edit config.sh to change the default prefix (/usr/local)
./download.sh
./install.sh
You can also compile each dependency, one by one:
......@@ -108,7 +111,7 @@ You can also compile each dependency, one by one:
make
make install
Note: if you install portaudio in /usr/local, don't forget to set pkg-config path with:
Note: if you install any package in /usr/local, don't forget to set pkg-config path with:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/
......@@ -175,8 +178,16 @@ How to enable IAX support?
--------------------------
Go inside libs directory and execute ./libiax2.sh script.
Run ./configure with --enable-iax2 option.
Then, run ./configure with --enable-iax2 option.
Debugging SFLPhone
------------------
You can use the --with-debug option with configure
./configure --with-debug
make
cd src
PATH=. ./gui/qt/sflphone-qt
Run-time troubleshooting
......@@ -219,7 +230,7 @@ Short description of content of source tree
audiodriver, rtp layer, audio codec ulaw, alaw and gsm.
- src/audio/gsm/ contains the implementation of gsm audiocodec library.
- src/audio/pacpp/ implements PortAudioCpp, a native C++ binding of
PortAudio V19.
PortAudio V19. (remove in sflphone 0.7)
- src/gui/ is the old directory that contains all about different user
interface.
- src/gui/server is the directory that talk (tcp socket on port 3999) to
......
......@@ -7,6 +7,7 @@ Management of account (add, remove, ...)
Management of exceptions
Remove all warnings in compilation
Better handling for an reINVITE request. (done?)
Mono channel, float for portaudio
For project dependencies:
------------------------
......
......@@ -129,16 +129,22 @@ dnl Check for exosip2
LP_CHECK_EXOSIP2
SFLPHONE_LIBS="$SFLPHONE_LIBS $EXOSIP_LIBS"
dnl Check for samplerate
AC_CHECK_HEADER([samplerate.h], [
AC_CHECK_LIB(samplerate, src_simple, [with_samplerate=yes], [with_samplerate=no])
], [ with_samplerate=no ]
)
AM_CONDITIONAL(USE_SAMPLERATE, test x$with_samplerate = xyes)
dnl AC_CHECK_HEADER([samplerate.h], [
dnl AC_CHECK_LIB(samplerate, src_simple, [with_samplerate=yes], [with_samplerate=no])
dnl ], [ with_samplerate=no ]
dnl )
dnl AM_CONDITIONAL(USE_SAMPLERATE, test x$with_samplerate = xyes)
dnl Check for GNU ccRTP
PKG_PROG_PKG_CONFIG
LIBSAMPLERATE_MIN_VERSION=0.1.2
PKG_CHECK_MODULES(samplerate, samplerate >= ${LIBSAMPLERATE_MIN_VERSION})
SFLPHONE_CFLAGS="$SFLPHONE_CFLAGS $samplerate_CFLAGS"
SFLPHONE_LIBS="$SFLPHONE_LIBS $samplerate_LIBS"
LIBCCGNU2_MIN_VERSION=1.3.1
PKG_CHECK_MODULES(libccgnu2, libccgnu2 >= ${LIBCCGNU2_MIN_VERSION})
SFLPHONE_CFLAGS="$SFLPHONE_CFLAGS $libccgnu2_CFLAGS"
......
......@@ -25,14 +25,6 @@ IAXSOURCES =
IAXHEADERS =
endif
if USE_SAMPLERATE
SAMPLERATE_FLAG=-DUSE_SAMPLERATE
SAMPLERATE_LIB =-lsamplerate
else
SAMPLERATE_FLAG=
SAMPLERATE_LIB=
endif
SUBDIRS = audio config gui $(ZEROCONFDIR)
sflphoned_SOURCES = eventthread.cpp main.cpp voIPLink.cpp \
......
......@@ -12,14 +12,6 @@ SPEEX_FLAG=
SPEEX_LIB=
endif
if USE_SAMPLERATE
SAMPLERATE_FLAG=-DUSE_SAMPLERATE
SAMPLERATE_LIB =-lsamplerate
else
SAMPLERATE_FLAG=
SAMPLERATE_LIB=
endif
libaudio_la_SOURCES = alaw.cpp audiofile.cpp g711.cpp tonelist.cpp \
audiortp.cpp dtmf.cpp tone.cpp audiocodec.cpp audiolayer.cpp audiodevice.cpp dtmfgenerator.cpp gsmcodec.cpp \
tonegenerator.cpp ulaw.cpp codecDescriptor.cpp \
......
......@@ -33,6 +33,9 @@ public:
AudioCodec(int payload, const std::string &codecName);
virtual ~AudioCodec(void);
/**
* @return the number of bytes decoded
*/
virtual int codecDecode(short *, unsigned char *, unsigned int) = 0;
virtual int codecEncode(unsigned char *, short *, unsigned int) = 0;
......
......@@ -23,6 +23,9 @@
#include "audiofile.h"
#include "codecDescriptor.h"
#include <fstream>
#include <math.h>
#include <samplerate.h>
AudioFile::AudioFile()
: AudioLoop()
......@@ -38,12 +41,13 @@ AudioFile::~AudioFile()
delete _ulaw;
}
// load file in mono format
bool
AudioFile::loadFile(const std::string& filename, unsigned int nbChannel=2)
AudioFile::loadFile(const std::string& filename, unsigned int sampleRate=8000)
{
_nbChannel = (nbChannel==2) ? 2 : 1;
if (_filename == filename) {
// if the filename was already load, with the same samplerate
// we do nothing
if (_filename == filename && _sampleRate == sampleRate) {
return true;
} else {
// reset to 0
......@@ -54,6 +58,7 @@ AudioFile::loadFile(const std::string& filename, unsigned int nbChannel=2)
// no filename to load
if (filename.empty()) {
_debug("Unable to open audio file: filename is empty\n");
return false;
}
......@@ -61,6 +66,7 @@ AudioFile::loadFile(const std::string& filename, unsigned int nbChannel=2)
file.open(filename.c_str(), std::fstream::in);
if (!file.is_open()) {
// unable to load the file
_debug("Unable to open audio file %s\n", filename.c_str());
return false;
}
......@@ -71,6 +77,7 @@ AudioFile::loadFile(const std::string& filename, unsigned int nbChannel=2)
// allocate memory:
char fileBuffer[length];
// read data as a block:
file.read (fileBuffer,length);
file.close();
......@@ -80,29 +87,61 @@ AudioFile::loadFile(const std::string& filename, unsigned int nbChannel=2)
// expandedsize should be exactly two time more, else failed
int16 monoBuffer[length];
unsigned int expandedsize = _ulaw->codecDecode (monoBuffer, (unsigned char *) fileBuffer, length);
if (expandedsize != length*sizeof(int16)) {
if (expandedsize != length*2) {
_debug("Audio file error on loading audio file!");
return false;
}
unsigned int nbSampling = expandedsize/sizeof(int16);
// we need to change the sample rating here:
// case 1: we don't have to resample : only do splitting and convert
if ( sampleRate == 8000 ) {
// just s
_size = nbSampling;
_buffer = new SFLDataFormat[_size];
// src to dest
for(unsigned int i=0; i<nbSampling; i++) {
_buffer[i] = SFLConvertInt16(monoBuffer[i]);
}
} else {
// case 2: we need to convert it and split it
// convert here
double factord = (double)sampleRate / 8000;
float* floatBufferIn = new float[nbSampling];
int sizeOut = (int)(ceil(factord*nbSampling));
src_short_to_float_array(monoBuffer, floatBufferIn, nbSampling);
SFLDataFormat* bufferTmp = new SFLDataFormat[sizeOut];
unsigned int int16size = expandedsize/sizeof(int16);
SRC_DATA src_data;
src_data.data_in = floatBufferIn;
src_data.input_frames = nbSampling;
src_data.output_frames = sizeOut;
src_data.src_ratio = factord;
if (_nbChannel == 2) {
_size = int16size<<1; // multiply by two
_buffer = new int16[_size];
#ifdef DATAFORMAT_IS_FLOAT
// case number 2.1: the output is float32 : convert directly in _bufferTmp
src_data.data_out = bufferTmp;
src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
#else
// case number 2.2: the output is int16 : convert and change to int16
float* floatBufferOut = new float[sizeOut];
src_data.data_out = floatBufferOut;
for(unsigned int i=0, k=0; i<int16size; i++) {
_buffer[k] = _buffer[k+1] = monoBuffer[i];
k+=2;
}
} else {
// copy the mono buffer to a mono buffer
_size = int16size;
_buffer = new int16[_size];
// src to dest
bcopy(monoBuffer, _buffer, expandedsize);
src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
src_float_to_short_array(floatBufferOut, bufferTmp, src_data.output_frames_gen);
delete [] floatBufferOut;
#endif
delete [] floatBufferIn;
nbSampling = src_data.output_frames_gen;
// if we are in mono, we send the bufferTmp location and don't delete it
// else we split the audio in 2 and put it into buffer
_size = nbSampling;
_buffer = bufferTmp; // just send the buffer pointer;
bufferTmp = 0;
}
return true;
}
......@@ -35,7 +35,7 @@ public:
AudioFile();
~AudioFile();
bool loadFile(const std::string& filename, unsigned int nbChannel/*=2*/);
bool loadFile(const std::string& filename, unsigned int sampleRate/*=8000*/);
void start() { _start = true; }
void stop() { _start = false; }
bool isStarted() { return _start; }
......
This diff is collapsed.
......@@ -27,14 +27,16 @@
#include "../global.h"
#include "ringbuffer.h"
#include "audiodevice.h"
#define FRAME_PER_BUFFER 160
class RingBuffer;
class ManagerImpl;
class AudioLayer {
public:
AudioLayer();
AudioLayer(ManagerImpl* manager);
~AudioLayer(void);
/*
......@@ -57,15 +59,10 @@ public:
int getMic(void *, int);
void flushMic();
/**
* Try to convert a int16 fromBuffer into a int16 to Buffer
* If the channel are the same, it only pass the address and the size of the from Buffer
* Else, it double or reduce by 2 the fromBuffer with a 0.5 conversion
*/
unsigned int convert(int16* fromBuffer, int fromChannel, unsigned int fromSize, int16** toBuffer, int toChannel);
int audioCallback (const void *, void *, unsigned long,
const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
int miniAudioCallback (const void *, void *, unsigned long,
const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
void setErrorMessage(const std::string& error) { _errorMessage = error; }
std::string getErrorMessage() { return _errorMessage; }
......@@ -75,8 +72,9 @@ public:
* accessor only
*/
unsigned int getSampleRate() { return _sampleRate; }
unsigned int getInChannel() { return _inChannel; }
unsigned int getOutChannel() { return _outChannel; }
int getDeviceCount();
AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask);
enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 };
......@@ -85,8 +83,11 @@ private:
RingBuffer _urgentRingBuffer;
RingBuffer _mainSndRingBuffer;
RingBuffer _micRingBuffer;
ManagerImpl* _manager; // augment coupling, reduce indirect access
// a audiolayer can't live without manager
portaudio::MemFunCallbackStream<AudioLayer> *_stream;
/**
* Sample Rate of SFLphone : should be 8000 for 8khz
* Added because we could change it in the futur
......@@ -94,18 +95,21 @@ private:
unsigned int _sampleRate;
/**
* Input channel (mic) should be 2 stereo or 1 mono
* Input channel (mic) should be 1 mono
*/
unsigned int _inChannel; // mic
/**
* Output channel (stereo) should be 2 stereo or 1 mono
* Output channel (stereo) should be 1 mono
*/
unsigned int _outChannel; // speaker
std::string _errorMessage;
// portaudio::AutoSystem autoSys;
ost::Mutex _mutex;
float *table_;
int tableSize_;
int leftPhase_;
};
#endif // _AUDIO_LAYER_H_
......
......@@ -28,16 +28,16 @@ AudioLoop::AudioLoop()
_buffer = 0;
_pos = 0;
_size = 0;
_nbChannel = 1;
_sampleRate = 0;
}
AudioLoop::~AudioLoop()
{
delete _buffer; _buffer = 0;
delete [] _buffer; _buffer = 0;
}
int
AudioLoop::getNext(int16* output, int nb, short volume)
AudioLoop::getNext(SFLDataFormat* output, int nb, short volume)
{
int copied = 0;
int block;
......@@ -48,7 +48,7 @@ AudioLoop::getNext(int16* output, int nb, short volume)
block = _size-pos;
}
// src, dest, len
bcopy(_buffer+pos, output, block<<1); // short>char conversion
bcopy(_buffer+pos, output, block*sizeof(SFLDataFormat)); // short>char conversion
if (volume!=100) {
for (int i=0;i<block;i++) {
*output = (*output * volume)/100;
......
......@@ -39,17 +39,18 @@ public:
* @param nb of int16 to send
* @return the number of int16 sent (nb*2)
*/
int getNext(int16* output, int nb, short volume=100);
int getNext(SFLDataFormat* output, int nb, short volume=100);
void reset() { _pos = 0; }
unsigned int getMonoSize() { return _size*_nbChannel; }
unsigned int getMonoSize() { return _size; }
unsigned int getSize() { return _size; }
protected:
int16* _buffer;
SFLDataFormat* _buffer;
int _size; // number of int16 inside the buffer, not the delay
int _pos; // current position, set to 0, when initialize
int _nbChannel;
int _sampleRate; // last samplerate
};
#endif // __AUDIOLOOP_H__
This diff is collapsed.
......@@ -26,9 +26,12 @@
#include <ccrtp/rtp.h>
#include <cc++/numbers.h>
#define RTP_FRAMES2SEND 160
class AudioLayer;
#include "../global.h"
/** maximum of byte inside an incoming packet
* 8000 sampling/s * 20s/1000 = 160
*/
#define RTP_20S_8KHZ_MAX 160
#define RTP_20S_48KHZ_MAX 960
class SIPCall;
///////////////////////////////////////////////////////////////////////////////
......@@ -36,32 +39,40 @@ class SIPCall;
///////////////////////////////////////////////////////////////////////////////
class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
public:
AudioRtpRTX (SIPCall *, AudioLayer*, bool);
AudioRtpRTX (SIPCall *, bool);
~AudioRtpRTX();
ost::Time *time; // For incoming call notification
virtual void run ();
private:
SIPCall* _ca;
AudioLayer* _audioDevice;
ost::RTPSession *_sessionSend;
ost::RTPSession *_sessionRecv;
ost::SymmetricRTPSession *_session;
SIPCall* _ca;
ost::RTPSession *_sessionSend;
ost::RTPSession *_sessionRecv;
ost::SymmetricRTPSession *_session;
ost::Semaphore _start;
bool _sym;
int _nbFrames;
#ifdef USE_SAMPLERATE
float *_floatBufferIn;
float *_floatBufferOut;
#endif
void initAudioRtpSession (void);
// void sendSessionFromMic (unsigned char*, int16*, int16*, int, int);
void sendSessionFromMic (unsigned char*, int16*, int16*, int);
// void receiveSessionForSpkr (int16*, int16*, int, int&);
void receiveSessionForSpkr (int16*, int16*, int&);
bool _sym;
/** When we receive data, we decode it inside this buffer */
int16* _receiveDataDecoded;
/** When we send data, we encode it inside this buffer*/
unsigned char* _sendDataEncoded;
/** After that we send the data inside this buffer if there is a format conversion or rate conversion */
/** Also use for getting mic-ringbuffer data */
SFLDataFormat* _dataAudioLayer;
/** Buffer for 8000hz samples in conversion */
float32* _floatBuffer8000;
/** Buffer for 48000hz samples in conversion */
float32* _floatBuffer48000;
/** Buffer for 8000hz samples for mic conversion */
int16* _intBuffer8000;
void initAudioRtpSession(void);
void sendSessionFromMic(int);
void receiveSessionForSpkr(int&);
};
///////////////////////////////////////////////////////////////////////////////
......
......@@ -23,8 +23,8 @@
#include "dtmf.h"
DTMF::DTMF (unsigned int sampleRate, unsigned int nbChannel)
: dtmfgenerator(sampleRate, nbChannel)
DTMF::DTMF (unsigned int sampleRate)
: dtmfgenerator(sampleRate)
{
currentTone = 0;
newTone = 0;
......@@ -41,7 +41,7 @@ DTMF::startTone (char code)
}
bool
DTMF::generateDTMF (int16* buffer, size_t n)
DTMF::generateDTMF (SFLDataFormat* buffer, size_t n)
{
if (!buffer) return false;
......
......@@ -36,16 +36,16 @@ public:
* Create a new DTMF.
* @param samplingRate frequency of the sample (ex: 8000 hz)
*/
DTMF (unsigned int sampleRate, unsigned int nbChannel);
DTMF (unsigned int sampleRate);
~DTMF (void);
void startTone (char);
/**
* Copy the sound inside the int16* buffer
* @param buffer : a int16* buffer
* Copy the sound inside the sampling* buffer
* @param buffer : a SFLDataFormat* buffer
* @param n :
*/
bool generateDTMF (int16* buffer, size_t n);
bool generateDTMF (SFLDataFormat* buffer, size_t n);
char currentTone;
char newTone;
......
......@@ -72,9 +72,8 @@ const char* DTMFException::what() const throw()
/*
* Initialize the generator
*/
DTMFGenerator::DTMFGenerator(unsigned int sampleRate, unsigned int nbChannel) : tone("", sampleRate, nbChannel)
DTMFGenerator::DTMFGenerator(unsigned int sampleRate) : tone("", sampleRate)
{
_nbChannel = nbChannel;
_sampleRate = sampleRate;
state.offset = 0;
state.sample = 0;
......@@ -95,7 +94,7 @@ DTMFGenerator::~DTMFGenerator() {
/*
* Get n samples of the signal of code code
*/
void DTMFGenerator::getSamples(int16* buffer, size_t n, unsigned char code) throw(DTMFException) {
void DTMFGenerator::getSamples(SFLDataFormat* buffer, size_t n, unsigned char code) throw(DTMFException) {
size_t i;
if (!buffer) {
throw DTMFException("Invalid parameter value");
......@@ -140,7 +139,7 @@ void DTMFGenerator::getSamples(int16* buffer, size_t n, unsigned char code) thro
* Get next n samples (continues where previous call to
* genSample or genNextSamples stopped
*/
void DTMFGenerator::getNextSamples(int16* buffer, size_t n) throw(DTMFException)
void DTMFGenerator::getNextSamples(SFLDataFormat* buffer, size_t n) throw(DTMFException)
{
size_t i;
......@@ -163,11 +162,11 @@ void DTMFGenerator::getNextSamples(int16* buffer, size_t n) throw(DTMFException)
/*
* Generate a tone sample
*/
int16* DTMFGenerator::generateSample(unsigned char code) throw (DTMFException) {
int16* ptr;
SFLDataFormat* DTMFGenerator::generateSample(unsigned char code) throw (DTMFException) {
SFLDataFormat* ptr;
try {
ptr = new int16[_sampleRate*_nbChannel];
ptr = new SFLDataFormat[_sampleRate];
if (!ptr) {
throw new DTMFException("No memory left");
return 0;
......
......@@ -64,19 +64,18 @@ private:
*/
struct DTMFState {
unsigned int offset; // Offset in the sample currently being played
int16* sample; // Currently generated code
SFLDataFormat* sample; // Currently generated code
};
DTMFState state;
static const DTMFTone tones[NUM_TONES];
int16* samples[NUM_TONES]; // Generated samples
SFLDataFormat* samples[NUM_TONES]; // Generated samples
/**
* Sampling rate of generated dtmf
*/
int _sampleRate;
int _nbChannel;
Tone tone;
public:
......@@ -85,27 +84,27 @@ public:
* and can build one DTMF.
* @param sampleRate frequency of the sample (ex: 8000 hz)
*/
DTMFGenerator(unsigned int sampleRate, unsigned int nbChannel);
DTMFGenerator(unsigned int sampleRate);
~DTMFGenerator();
/*
* Get n samples of the signal of code code
* @param buffer a int16 pointer to an allocated buffer
* @param n number of int16 to get, should be lower or equal to buffer size
* @param buffer a SFLDataFormat pointer to an allocated buffer
* @param n number of sampling to get, should be lower or equal to buffer size
* @parma code dtmf code to get sound
*/
void getSamples(int16* buffer, size_t n, unsigned char code) throw (DTMFException);
void getSamples(SFLDataFormat* buffer, size_t n, unsigned char code) throw (DTMFException);
/*
* Get next n samples (continues where previous call to
* genSample or genNextSamples stopped
* @param buffer a int16 pointer to an allocated buffer
* @param n number of int16 to get, should be lower or equal to buffer size
* @param buffer a SFLDataFormat pointer to an allocated buffer
* @param n number of sampling to get, should be lower or equal to buffer size
*/
void getNextSamples(int16* buffer, size_t n) throw (DTMFException);
void getNextSamples(SFLDataFormat* buffer, size_t n) throw (DTMFException);
private:
int16* generateSample(unsigned char code) throw (DTMFException);
SFLDataFormat* generateSample(unsigned char code) throw (DTMFException);
};
......
......@@ -92,7 +92,7 @@ RingBuffer::Put(void* buffer, int toCopy, unsigned short volume) {
// put the data inside the buffer.
if (volume!=100) {
int16* src16 = (int16*)src;
SFLDataFormat* src16 = (SFLDataFormat*)src;
int int16len = (block >> 1);
for (int i=0; i < int16len; i++) { src16[i] = src16[i] * volume / 100; }
}
......@@ -142,7 +142,7 @@ RingBuffer::Get(void *buffer, int toCopy, unsigned short volume) {
block = mBufferSize - mStart;
if(volume!=100) {
int16* start = (int16*)(mBuffer + mStart);
SFLDataFormat* start = (SFLDataFormat*)(mBuffer + mStart);
int int16len = (block >> 1);
for (int i=0; i<int16len; i++) { start[i] = start[i] * volume / 100; }
}
......
......@@ -23,11 +23,8 @@
#include "tone.h"
#include <math.h>
int INT16_AMPLITUDE = 32767;
Tone::Tone(const std::string& definition, unsigned int sampleRate, unsigned int nbChannel) : AudioLoop()
Tone::Tone(const std::string& definition, unsigned int sampleRate) : AudioLoop()
{
_nbChannel = nbChannel;
_sampleRate = sampleRate;
genBuffer(definition); // allocate memory with definition parameter
}
......@@ -42,8 +39,8 @@ Tone::genBuffer(const std::string& definition)
if (definition.empty()) { return; }
_size = 0;
int16 *buffer = new int16[SIZEBUF]; //1kb
int16 *bufferPos = buffer;
SFLDataFormat* buffer = new SFLDataFormat[SIZEBUF]; //1kb
SFLDataFormat* bufferPos = buffer;
// Number of format sections
unsigned int posStart = 0; // position of precedent comma
......@@ -97,37 +94,31 @@ Tone::genBuffer(const std::string& definition)
genSin(bufferPos, freq1, freq2, count);
// To concatenate the different buffers for each section.
_size += (count * _nbChannel);
bufferPos += (count * _nbChannel);
_size += (count);
bufferPos += (count);
}
posStart = posEnd+1;
} while (posStart < deflen);
_buffer = new int16[_size];
_buffer = new SFLDataFormat[_size];
// src, dest, tocopy
bcopy(buffer, _buffer, _size<<1); // copy char, not int16..
bcopy(buffer, _buffer, _size*sizeof(SFLDataFormat)); // copy char, not SFLDataFormat.
delete[] buffer; buffer=0; bufferPos=0;
}
void
Tone::genSin(int16 *buffer, int frequency1, int frequency2, int nb)
Tone::genSin(SFLDataFormat* buffer, int frequency1, int frequency2, int nb)
{
double var1 = (double)2 * (double)M_PI * (double)frequency1 / (double)_sampleRate;
double var2 = (double)2 * (double)M_PI * (double)frequency2 / (double)_sampleRate;
double pi2 = 6.28318520;
double var1 = pi2 * (double)frequency1 / (double)_sampleRate;
double var2 = pi2 * (double)frequency2 / (double)_sampleRate;
// softer
double amp = (double)(INT16_AMPLITUDE >> 4);
if (_nbChannel == 2) { // stereo
int k = 0;
for(int t = 0; t < nb; t++) {
k = t << 1; // double channel : left/right
buffer[k] = buffer[k+1] = (int16)(amp * ((sin(var1 * t) + sin(var2 * t))));
}
} else {
for(int t = 0; t < nb; t++) {
buffer[t] = (int16)(amp * ((sin(var1 * t) + sin(var2 * t))));
}
double amp = (double)SFLDataAmplitude;
for(int t = 0; t < nb; t++) {
buffer[t] = (SFLDataFormat)(amp * ((sin(var1 * t) + sin(var2 * t))));
}
}
......@@ -38,7 +38,7 @@ public:
* @param definition String that contain frequency/time of the tone
* @param sampleRate SampleRating of audio tone
*/
Tone(const std::string& definition, unsigned int sampleRate, unsigned int nbChannel);
Tone(const std::string& definition, unsigned int sampleRate);
~Tone();