Commit 420672da authored by llea's avatar llea
Browse files

Changes about audiodriversportaudio

parent 3ad59d5b
......@@ -101,8 +101,8 @@ OBJS = \
udp.o
#start: check prereq all
start:check all
start: check prereq all
#start:check all
check:
ifeq ($(CONFIGURE_CONF),../configure.conf)
......
......@@ -29,10 +29,10 @@
AudioDriversPortAudio::AudioDriversPortAudio (Manager* manager) {
_manager = manager;
mydata.dataToAddRem = 0;
mydata.dataFilled = 0;
mydata.urg_remain = 0;
mydata.dataIn = NULL;
mydata.dataOut = NULL;
mydata.urg_data = NULL;
this->initDevice();
}
......@@ -76,13 +76,13 @@ bool
AudioDriversPortAudio::openDevice (void) {
int err = Pa_OpenDefaultStream (
&_stream, /* passes back stream pointer */
1, /* mono input */
1, /* mono output */
2, /* input channel */
2, /* output channel */
paFloat32, /* 32 bit float output */
SAMPLING_RATE, /* sample rate */
FRAME_PER_BUFFER, /* frames per buffer */
audioCallback, /* specify our custom callback */
&mydata); /* pass our data through to callback */
&mydata); /* pass our data through to callback */
if (err != paNoError) {
_debug ("PortAudio error in Pa_OpenDefaultStream: %s\n", Pa_GetErrorText(err));
......@@ -95,11 +95,15 @@ AudioDriversPortAudio::openDevice (void) {
int
AudioDriversPortAudio::readBuffer (void *ptr, int bytes) {
(void) ptr;
(void) bytes;
return 1;
}
int
AudioDriversPortAudio::writeBuffer (void *ptr, int len) {
(void) ptr;
(void) len;
return 1;
}
......@@ -107,11 +111,13 @@ int
AudioDriversPortAudio::startStream(void)
{
int err;
err = Pa_StartStream (_stream);
if( err != paNoError ) {
_debug ("PortAudio error in Pa_StartStream: %s\n", Pa_GetErrorText(err));
return 0;
if (!Pa_IsStreamActive(_stream)) {
err = Pa_StartStream (_stream);
if( err != paNoError ) {
_debug ("PortAudio error in Pa_StartStream: %s\n",
Pa_GetErrorText(err));
return 0;
}
}
return 1;
......@@ -122,11 +128,15 @@ AudioDriversPortAudio::stopStream(void)
{
int err;
err = Pa_StopStream (_stream);
if( err != paNoError ) {
_debug ("PortAudio error in Pa_StopStream: %s\n", Pa_GetErrorText(err));
return 0;
if (!Pa_IsStreamStopped(_stream)) {
err = Pa_StopStream (_stream);
if( err != paNoError ) {
_debug ("PortAudio error in Pa_StopStream: %s\n",
Pa_GetErrorText(err));
return 0;
}
}
return 1;
}
......@@ -168,52 +178,31 @@ AudioDriversPortAudio::audioCallback (const void *inputBuffer,
float32 *out = (float32 *) outputBuffer;
paData* data = (paData*) userData;
unsigned int i;
int i;
int it;
#if 1
/* Fill output buffer */
int j = data->dataToAddRem;
int k = data->dataFilled;
for (i = 0; i < framesPerBuffer; i++) {
if (j > 0 && k < j) {
*out++ = data->dataToAdd[i+k];
for (i = 0; i < (int)framesPerBuffer; i++) {
it = 2*i;
if (data->urg_remain - i > 0) {
out[it] = out[it+1] = data->urg_ptr[i];
} else {
*out++ = data->dataOut[i];
out[it] = out[it+1] = data->dataOut[i];
}
}
k += framesPerBuffer;
if (k >= j) {
data->dataFilled = 0;
}
if ((data->urg_remain -i) > 0) {
data->urg_ptr +=i;
data->urg_remain-= i;
} else {
data->dataFilled = k;
data->urg_remain = 0;
}
#endif
/* Read input buffer */
if (data->dataIn != NULL) {
memcpy (data->dataIn, in, sizeof(float32) * framesPerBuffer);
}
#if 0
int j = data->dataToAddRem;
/* Fill output buffer */
for (i = 0; i < framesPerBuffer; i++) {
if (j > 0 && j >= i) {
*out++ = data->dataToAdd[j-i];
} else {
*out++ = data->dataOut[i];
}
}
j = j - i;
if (j > 0) {
data->dataToAddRem = j;
} else {
data->dataToAddRem = 0;
// cout << "please FREE data->dataToAdd now!!!" << endl;
memcpy (data->dataIn, in, 2*sizeof(float32) * framesPerBuffer);
}
#endif
return paContinue;
}
#endif // defined(AUDIO_PORTAUDIO)
......
......@@ -34,9 +34,9 @@ public:
struct paData {
float32 *dataIn; // From mic
float32 *dataOut; // To spk
float32 *dataToAdd; // To spk
int dataToAddRem;
int dataFilled;
float32 *urg_data; // data in priority
float32 *urg_ptr;
int urg_remain; // data remained in urg_data
};
paData mydata;
......
......@@ -150,6 +150,7 @@ AudioRtpRTX::run (void) {
int countTime = 0;
int16 *data_for_speakers = NULL;
float32 *data_for_speakers_float = NULL;
float32 *data_for_speakers_float_tmp = NULL;
data_from_mic = new float32[1024];
data_from_mic_tmp = new float32[1024];
......@@ -236,6 +237,7 @@ AudioRtpRTX::run (void) {
_manager->getAudioDriver()->mydata.dataIn = data_mute;
}
// Control volume for micro
for (int j = 0; j < size; j++) {
data_from_mic_tmp[j] = data_from_mic[j] *
_manager->getMicroVolume()/100;
......@@ -284,9 +286,15 @@ AudioRtpRTX::run (void) {
data_for_speakers_float = new float32[expandedSize];
ac->int16ToFloat32 (data_for_speakers, data_for_speakers_float,
expandedSize);
// control volume for speakers
data_for_speakers_float_tmp = new float32[expandedSize];
for (int j = 0; j < expandedSize; j++) {
data_for_speakers_float_tmp[j] = data_for_speakers_float[j] *
_manager->getSpkrVolume()/100;
}
// Set decoded data to sound device
_manager->getAudioDriver()->mydata.dataOut = data_for_speakers_float;
_manager->getAudioDriver()->mydata.dataOut =data_for_speakers_float_tmp;
// Notify (with a bip) an incoming call when there is already a call
countTime += time->getSecond();
......@@ -304,14 +312,13 @@ AudioRtpRTX::run (void) {
Thread::sleep(TimerPort::getTimer());
TimerPort::incTimer(frameSize); // 'frameSize' ms
if (!_manager->getAudioDriver()->isStreamActive()) {
_manager->getAudioDriver()->mydata.dataToAddRem = 0;
_manager->getAudioDriver()->startStream();
}
// Start PortAudio
_manager->getAudioDriver()->startStream();
}
delete[] data_for_speakers;
delete[] data_for_speakers_float;
delete[] data_for_speakers_float_tmp;
delete[] data_from_mic;
delete[] data_from_mic_int16;
delete[] data_from_mic_tmp;
......
......@@ -28,7 +28,13 @@
CodecDescriptor::CodecDescriptor (int payload)
{
_payload = payload;
_codecName = "";
_codecName = rtpmapPayload(_payload);
}
CodecDescriptor::CodecDescriptor (const string& name)
{
_codecName = name;
_payload = matchPayloadCodec(name);
}
CodecDescriptor::CodecDescriptor (int payload, const string& name)
......
......@@ -45,6 +45,7 @@ class CodecDescriptor
{
public:
CodecDescriptor (int payload);
CodecDescriptor (const string& name);
CodecDescriptor (int payload, const string& name);
~CodecDescriptor (void);
......
......@@ -172,8 +172,7 @@ float32* DTMFGenerator::generateSample(unsigned char code) throw (DTMFException)
return 0;
}
generateSin(tones[code].higher, tones[code].lower,
SAMPLING_RATE, ptr);
generateSin(tones[code].higher, tones[code].lower, ptr);
return ptr;
// } catch(...) {
......
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
<meta name="Author" content="Phil Burk">
<meta name="Description" content="PortAudio Docs, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
<title>PortAudio Docs</title>
</head>
<body>
&nbsp;
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
<tr>
<td>
<center>
<h1>
PortAudio Documentation</h1></center>
</td>
</tr>
</table></center>
<p>Copyright 2000 Phil Burk and Ross Bencina
<br>&nbsp;
<h3>
<a href="portaudio_h.txt">API Reference</a></h3>
<blockquote>The Application Programmer Interface is documented in "portaudio.h".</blockquote>
<h3>
<a href="pa_tutorial.html">Tutorial</a></h3>
<blockquote>Describes how to write audio programs using the PortAudio API.</blockquote>
<h3>
<a href="pa_impl_guide.html">Implementation Guide</a></h3>
<blockquote>Describes how to write an implementation of PortAudio for a
new computer platform.</blockquote>
<h3>
<a href="portaudio_icmc2001.pdf">Paper Presented at ICMC2001</a> (PDF)</h3>
<blockquote>Describes the PortAudio API and discusses implementation issues.
Written July 2001.</blockquote>
<h3>
<a href="latency.html">Improving Latency</a></h3>
<blockquote>How to tune your computer to achieve the lowest possible audio
delay.</blockquote>
<h3>
<a href="proposals.html">Proposed Changes</a></h3>
<blockquote>Describes API changes being considered by the developer community.
Feedback welcome.</blockquote>
<a href="http://www.portaudio.com/">Return to PortAudio Home Page</a>
</body>
</html>
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
<meta name="Author" content="Phil Burk">
<meta name="Description" content="Internal docs. How a stream is started or stopped.">
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
<title>PortAudio Implementation - Start/Stop</title>
</head>
<body>
&nbsp;
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
<tr>
<td>
<center>
<h1>
<a href="http://www.portaudio.com">PortAudio</a> Latency</h1></center>
</td>
</tr>
</table></center>
<p>This page discusses the issues of audio latency for <a href="http://www.portaudio.com">PortAudio</a>
. It offers suggestions on how to lower latency to improve the responsiveness
of applications.
<blockquote><b><a href="#what">What is Latency?</a></b>
<br><b><a href="#portaudio">PortAudio and Latency</a></b>
<br><b><a href="#macintosh">Macintosh</a></b>
<br><b><a href="#unix">Unix</a></b>
<br><b><a href="#windows">WIndows</a></b></blockquote>
By Phil Burk, Copyright 2002 Phil Burk and Ross Bencina
<h2>
<a NAME="what"></a>What is Latency?</h2>
Latency is basically longest time that you have to wait before you obtain
a desired result. For digital audio output it is the time between making
a sound in software and finally hearing it.
<p>Consider the example of pressing a key on the ASCII keyboard to play
a note. There are several stages in this process which each contribute
their own latency. First the operating system must respond to the keypress.
Then the audio signal generated must work its way through the PortAudio
buffers. Then it must work its way through the audio card hardware. Then
it must go through the audio amplifier which is very quick and then travel
through the air. Sound travels at abous one foot per millisecond through
air so placing speakers across the room can add 5-20 msec of delay.
<p>The reverse process occurs when recording or responding to audio input.
If you are processing audio, for example if you implement a software guitar
fuzz box, then you have both the audio input and audio output latencies
added together.
<p>The audio buffers are used to prevent glitches in the audio stream.
The user software writes audio into the output buffers. That audio is read
by the low level audio driver or by DMA and sent to the DAC. If the computer
gets busy doing something like reading the disk or redrawing the screen,
then it may not have time to fill the audio buffer. The audio hardware
then runs out of audio data, which causes a glitch. By using a large enough
buffer we can ensure that there is always enough audio data for the audio
hardware to play. But if the buffer is too large then the latency is high
and the system feels sluggish. If you play notes on the keyboard then the
"instrument" will feel unresponsive. So you want the buffers to be as small
as possible without glitching.
<h2>
<a NAME="portaudio"></a>PortAudio and Latency</h2>
The only delay that PortAudio can control is the total length of its buffers.
The Pa_OpenStream() call takes two parameters: numBuffers and framesPerBuffer.
The latency is also affected by the sample rate which we will call framesPerSecond.
A frame is a set of samples that occur simultaneously. For a stereo stream,
a frame is two samples.
<p>The latency in milliseconds due to this buffering&nbsp; is:
<blockquote><tt>latency_msec = 1000 * numBuffers * framesPerBuffer / framesPerSecond</tt></blockquote>
This is not the total latency, as we have seen, but it is the part we can
control.
<p>If you call Pa_OpenStream() with numBuffers equal to zero, then PortAudio
will select a conservative number that will prevent audio glitches. If
you still get glitches, then you can pass a larger value for numBuffers
until the glitching stops. if you try to pass a numBuffers value that is
too small, then PortAudio will use its own idea of the minimum value.
<p>PortAudio decides on the minimum number of buffers in a conservative
way based on the frameRate, operating system and other variables. You can
query the value that PortAudio will use by calling:
<blockquote><tt>int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate
);</tt></blockquote>
On some systems you can override the PortAudio minimum if you know your
system can handle a lower value. You do this by setting an environment
variable called PA_MIN_LATENCY_MSEC which is read by PortAudio when it
starts up. This is supported on the PortAudio implementations for Windows
MME, Windows DirectSound, and Unix OSS.
<h2>
<a NAME="macintosh"></a>Macintosh</h2>
The best thing you can do to improve latency on Mac OS 8 and 9 is to turn
off Virtual Memory. PortAudio V18 will detect that Virtual Memory is turned
off and use a very low latency.
<p>For Mac OS X the latency is very low because Apple Core Audio is so
well written. You can set the PA_MIN_LATENCY_MSEC variable using:
<blockquote><tt>setenv PA_MIN_LATENCY_MSEC 4</tt></blockquote>
<h2>
<a NAME="unix"></a>Unix</h2>
PortAudio under Unix currently uses a backgroud thread that reads and writes
to OSS. This gives you decent but not great latency. But if you raise the
priority of the background thread to a very priority then you can get under
10 milliseconds latency. In order to raise your priority you must run the
PortAudio program as root! You must also set PA_MIN_LATENCY_MSEC using
the appropriate command for your shell.
<h2>
<a NAME="windows"></a>Windows</h2>
Latency under Windows is a complex issue because of all the alternative
operating system versions and device drivers. I have seen latency range
from 8 milliseconds to 400 milliseconds. The worst case is when using Windows
NT. Windows 98 is a little better, and Windows XP can be quite good if
properly tuned.
<p>The underlying audio API also makes a lot of difference. If the audio
device has its own DirectSound driver then DirectSound can often provide
better latency than WMME. But if a real DirectSound driver is not available
for your device then it is emulated using WMME and the latency can be very
high. That's where I saw the 400 millisecond latency. The ASIO implementation
is generally very good and will give the lowest latency if available.
<p>You can set the PA_MIN_LATENCY_MSEC variable to 50, for example, by
entering in MS-DOS:
<blockquote><tt>set PA_MIN_LATENCY_MSEC=50</tt></blockquote>
If you enter this in a DOS window then you must run the PortAudio program
from that same window for the variable to have an effect. You can add that
line to your C:\AUTOEXEC.BAT file and reboot if you want it to affect any
PortAudio based program.
<p>For Windows XP, you can set environment variables as follows:
<ol>
<li>
Select "Control Panel" from the "Start Menu".</li>
<li>
Launch the "System" Control Panel</li>
<li>
Click on the "Advanced" tab.</li>
<li>
Click on the "Environment Variables" button.</li>
<li>
Click "New" button under&nbsp; User Variables.</li>
<li>
Enter PA_MIN_LATENCY_MSEC for the name and some optimistic number for the
value.</li>
<li>
Click OK, OK, OK.</li>
</ol>
<h3>
Improving Latency on Windows</h3>
There are several steps you can take to improve latency under windows.
<ol>
<li>
Avoid reading or writng to disk when doing audio.</li>
<li>
Turn off all automated background tasks such as email clients, virus scanners,
backup programs, FTP servers, web servers, etc. when doing audio.</li>
<li>
Disconnect from the network to prevent network traffic from interrupting
your CPU.</li>
</ol>
<b>Important: </b>Windows XP users can also tune the OS to favor background
tasks, such as audio, over foreground tasks, such as word processing. I
lowered my latency from 40 to 10 milliseconds using this simple technique.
<ol>
<li>
Select "Control Panel" from the "Start Menu".</li>
<li>
Launch the "System" Control Panel</li>
<li>
Click on the "Advanced" tab.</li>
<li>
Click on the "Settings" button in the Performance area.</li>
<li>
Click on the "Advanced" tab.</li>
<li>
Select "Background services" in the Processor Scheduling area.</li>
<li>
Click OK, OK.</li>
</ol>
Please let us know if you have others sugestions for lowering latency.
<br>&nbsp;
<br>&nbsp;
</body>
</html>
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
<meta name="Author" content="Phil Burk">
<meta name="Description" content="Internal docs. How a stream is started or stopped.">
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
<title>PortAudio Implementation - Start/Stop</title>
</head>
<body>
&nbsp;
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
<tr>
<td>
<center>
<h1>
<a href="http://www.portaudio.com">PortAudio</a> Implementation Guide</h1></center>
</td>
</tr>
</table></center>
<p>This document describes how to implement the PortAudio API on a new
computer platform. Implementing PortAudio on a new platform, makes it possible
to port many existing audio applications to that platform.
<p>By Phil Burk
<br>Copyright 2000 Phil Burk and Ross Bencina
<p>Note that the license says: <b>"Any person wishing to distribute modifications
to the Software is requested to send the modifications to the original
developer so that they can be incorporated into the canonical version."</b>.
So when you have finished a new implementation, please send it back to
us at&nbsp; "<a href="http://www.portaudio.com">http://www.portaudio.com</a>"
so that we can make it available for other users. Thank you!
<h2>
Download the Latest PortAudio Implementation</h2>
Always start with the latest implementation available at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>".
Look for the nightly snapshot under the CVS section.
<h2>
Select an Existing Implementation as a Basis</h2>
The fastest way to get started is to take an existing implementation and
translate it for your new platform. Choose an implementation whose architecture
is as close as possible to your target.
<ul>
<li>
DirectSound Implementation - pa_win_ds - Uses a timer callback for the
background "thread". Polls a circular buffer and writes blocks of data
to keep it full.</li>
<li>
Windows MME - pa_win_wmme - Spawns an actual Win32 thread. Writes blocks
of data to the HW device and waits for events that signal buffer completion.</li>
<li>
Linux OSS - pa_linux - Spawns a real thread that writes to the "/dev/dsp"
stream using blocking I/O calls.</li>
</ul>
When you write a new implementation, you will be using some code that is
in common with all implementations. This code is in the folder "pa_common".
It provides various functions such as parameter checking, error code to
text conversion, sample format conversion, clipping and dithering, etc.
<p>The code that you write will go into a separate folder called "pa_{os}_{api}".
For example, code specific to the DirectSound interface for Windows goes
in "pa_win_ds".
<h2>
Read Docs and Code</h2>
Famialiarize yourself with the system by reading the documentation provided.
here is a suggested order:
<ol>
<li>
User Programming <a href="pa_tutorial.html">Tutorial</a></li>
<li>
Header file "pa_common/portaudio.h" which defines API.</li>
<li>
Header file "pa_common/pa_host.h" for host dependant code. This definces
the routine you will need to provide.</li>
<li>
Shared code in "pa_common/pa_lib.c".</li>
<li>
Docs on Implementation of <a href="pa_impl_startstop.html">Start/Stop</a>
code.</li>
</ol>
<h2>
Implement&nbsp; Output to Default Device</h2>
Now we are ready to crank some code. For instant gratification, let's try
to play a sine wave.
<ol>
<li>
Link the test program "pa_tests/patest_sine.c" with the file "pa_lib.c"
and the implementation specific file you are creating.</li>
<li>
For now, just stub out the device query code and the audio input code.</li>
<li>
Modify PaHost_OpenStream() to open your default target device and get everything
setup.</li>