Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
df1f3209
提交
df1f3209
authored
3月 30, 2006
作者:
Michael Jerris
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dos2unix
git-svn-id:
http://svn.freeswitch.org/svn/freeswitch/trunk@968
d0543943-73ff-0310-b7d9-9358b9ac24b2
上级
0232f398
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
698 行增加
和
698 行删除
+698
-698
pablio.c
src/mod/endpoints/mod_portaudio/pablio.c
+291
-291
pablio.h
src/mod/endpoints/mod_portaudio/pablio.h
+109
-109
ringbuffer.c
src/mod/endpoints/mod_portaudio/ringbuffer.c
+195
-195
ringbuffer.h
src/mod/endpoints/mod_portaudio/ringbuffer.h
+103
-103
没有找到文件。
src/mod/endpoints/mod_portaudio/pablio.c
浏览文件 @
df1f3209
/*
/*
* $Id: pablio.c,v 1.1.1.1.4.4 2003/03/13 17:28:33 philburk Exp $
* $Id: pablio.c,v 1.1.1.1.4.4 2003/03/13 17:28:33 philburk Exp $
* pablio.c
* pablio.c
* Portable Audio Blocking Input/Output utility.
* Portable Audio Blocking Input/Output utility.
*
*
* Author: Phil Burk, http://www.softsynth.com
* Author: Phil Burk, http://www.softsynth.com
*
*
* This program uses the PortAudio Portable Audio Library.
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* included in all copies or substantial portions of the Software.
*
*
* Any person wishing to distribute modifications to the Software is
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
* they can be incorporated into the canonical version.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
*/
/* History:
/* History:
* PLB021214 - check for valid stream in CloseAudioStream() to prevent hang.
* PLB021214 - check for valid stream in CloseAudioStream() to prevent hang.
* add timeOutMSec to CloseAudioStream() to prevent hang.
* add timeOutMSec to CloseAudioStream() to prevent hang.
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
#include <math.h>
#include "portaudio.h"
#include "portaudio.h"
#include "ringbuffer.h"
#include "ringbuffer.h"
#include "pablio.h"
#include "pablio.h"
#include <string.h>
#include <string.h>
/************************************************************************/
/************************************************************************/
/******** Constants *****************************************************/
/******** Constants *****************************************************/
/************************************************************************/
/************************************************************************/
#define FRAMES_PER_BUFFER (256)
#define FRAMES_PER_BUFFER (256)
/************************************************************************/
/************************************************************************/
/******** Prototypes ****************************************************/
/******** Prototypes ****************************************************/
/************************************************************************/
/************************************************************************/
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
un
signed
long
framesPerBuffer
,
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
unsigned
long
framesPerBuffer
,
P
aTimestamp
outTime
,
void
*
userData
);
PaTimestamp
outTime
,
void
*
userData
);
s
tatic
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
);
static
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
);
s
tatic
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
);
static
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
);
/************************************************************************/
/************************************************************************/
/******** Functions *****************************************************/
/******** Functions *****************************************************/
/************************************************************************/
/************************************************************************/
/* Called from PortAudio.
/* Called from PortAudio.
* Read and write data only if there is room in FIFOs.
* Read and write data only if there is room in FIFOs.
*/
*/
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
u
nsigned
long
framesPerBuffer
,
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
unsigned
long
framesPerBuffer
,
PaTimestamp
outTime
,
void
*
userData
)
PaTimestamp
outTime
,
void
*
userData
)
{
{
P
ABLIO_Stream
*
data
=
(
PABLIO_Stream
*
)
userData
;
PABLIO_Stream
*
data
=
(
PABLIO_Stream
*
)
userData
;
l
ong
numBytes
=
data
->
bytesPerFrame
*
framesPerBuffer
;
long
numBytes
=
data
->
bytesPerFrame
*
framesPerBuffer
;
(
void
)
outTime
;
(
void
)
outTime
;
/* This may get called with NULL inputBuffer during initial setup. */
/* This may get called with NULL inputBuffer during initial setup. */
if
(
inputBuffer
!=
NULL
)
if
(
inputBuffer
!=
NULL
)
{
{
R
ingBuffer_Write
(
&
data
->
inFIFO
,
inputBuffer
,
numBytes
);
RingBuffer_Write
(
&
data
->
inFIFO
,
inputBuffer
,
numBytes
);
}
}
i
f
(
outputBuffer
!=
NULL
)
if
(
outputBuffer
!=
NULL
)
{
{
i
nt
i
;
int
i
;
i
nt
numRead
=
RingBuffer_Read
(
&
data
->
outFIFO
,
outputBuffer
,
numBytes
);
int
numRead
=
RingBuffer_Read
(
&
data
->
outFIFO
,
outputBuffer
,
numBytes
);
/* Zero out remainder of buffer if we run out of data. */
/* Zero out remainder of buffer if we run out of data. */
for
(
i
=
numRead
;
i
<
numBytes
;
i
++
)
for
(
i
=
numRead
;
i
<
numBytes
;
i
++
)
{
{
((
char
*
)
outputBuffer
)[
i
]
=
0
;
((
char
*
)
outputBuffer
)[
i
]
=
0
;
}
}
}
}
return
0
;
return
0
;
}
}
/* Allocate buffer. */
/* Allocate buffer. */
static
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
)
static
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
)
{
{
l
ong
numBytes
=
numFrames
*
bytesPerFrame
;
long
numBytes
=
numFrames
*
bytesPerFrame
;
c
har
*
buffer
=
(
char
*
)
malloc
(
numBytes
);
char
*
buffer
=
(
char
*
)
malloc
(
numBytes
);
i
f
(
buffer
==
NULL
)
if
(
buffer
==
NULL
)
return
paInsufficientMemory
;
return
paInsufficientMemory
;
memset
(
buffer
,
0
,
numBytes
);
memset
(
buffer
,
0
,
numBytes
);
return
(
PaError
)
RingBuffer_Init
(
rbuf
,
numBytes
,
buffer
);
return
(
PaError
)
RingBuffer_Init
(
rbuf
,
numBytes
,
buffer
);
}
}
/* Free buffer. */
/* Free buffer. */
static
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
)
static
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
)
{
{
i
f
(
rbuf
->
buffer
)
if
(
rbuf
->
buffer
)
free
(
rbuf
->
buffer
);
free
(
rbuf
->
buffer
);
r
buf
->
buffer
=
NULL
;
rbuf
->
buffer
=
NULL
;
r
eturn
paNoError
;
return
paNoError
;
}
}
/************************************************************
/************************************************************
* Write data to ring buffer.
* Write data to ring buffer.
* Will not return until all the data has been written.
* Will not return until all the data has been written.
*/
*/
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
{
{
l
ong
bytesWritten
;
long
bytesWritten
;
c
har
*
p
=
(
char
*
)
data
;
char
*
p
=
(
char
*
)
data
;
l
ong
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
long
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
w
hile
(
numBytes
>
0
)
while
(
numBytes
>
0
)
{
{
b
ytesWritten
=
RingBuffer_Write
(
&
aStream
->
outFIFO
,
p
,
numBytes
);
bytesWritten
=
RingBuffer_Write
(
&
aStream
->
outFIFO
,
p
,
numBytes
);
n
umBytes
-=
bytesWritten
;
numBytes
-=
bytesWritten
;
p
+=
bytesWritten
;
p
+=
bytesWritten
;
i
f
(
numBytes
>
0
)
if
(
numBytes
>
0
)
Pa_Sleep
(
10
);
Pa_Sleep
(
10
);
}
}
return
numFrames
;
return
numFrames
;
}
}
/************************************************************
/************************************************************
* Read data from ring buffer.
* Read data from ring buffer.
* Will not return until all the data has been read.
* Will not return until all the data has been read.
*/
*/
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
{
{
l
ong
bytesRead
;
long
bytesRead
;
c
har
*
p
=
(
char
*
)
data
;
char
*
p
=
(
char
*
)
data
;
l
ong
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
long
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
w
hile
(
numBytes
>
0
)
while
(
numBytes
>
0
)
{
{
b
ytesRead
=
RingBuffer_Read
(
&
aStream
->
inFIFO
,
p
,
numBytes
);
bytesRead
=
RingBuffer_Read
(
&
aStream
->
inFIFO
,
p
,
numBytes
);
n
umBytes
-=
bytesRead
;
numBytes
-=
bytesRead
;
p
+=
bytesRead
;
p
+=
bytesRead
;
i
f
(
numBytes
>
0
)
if
(
numBytes
>
0
)
Pa_Sleep
(
10
);
Pa_Sleep
(
10
);
}
}
return
numFrames
;
return
numFrames
;
}
}
/************************************************************
/************************************************************
* Return the number of frames that could be written to the stream without
* Return the number of frames that could be written to the stream without
* having to wait.
* having to wait.
*/
*/
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
)
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
)
{
{
i
nt
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
int
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
r
eturn
bytesEmpty
/
aStream
->
bytesPerFrame
;
return
bytesEmpty
/
aStream
->
bytesPerFrame
;
}
}
/************************************************************
/************************************************************
* Return the number of frames that are available to be read from the
* Return the number of frames that are available to be read from the
* stream without having to wait.
* stream without having to wait.
*/
*/
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
)
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
)
{
{
int
bytesFull
=
RingBuffer_GetReadAvailable
(
&
aStream
->
inFIFO
);
int
bytesFull
=
RingBuffer_GetReadAvailable
(
&
aStream
->
inFIFO
);
return
bytesFull
/
aStream
->
bytesPerFrame
;
return
bytesFull
/
aStream
->
bytesPerFrame
;
}
}
/************************************************************/
/************************************************************/
static
unsigned
long
RoundUpToNextPowerOf2
(
unsigned
long
n
)
static
unsigned
long
RoundUpToNextPowerOf2
(
unsigned
long
n
)
{
{
l
ong
numBits
=
0
;
long
numBits
=
0
;
i
f
(((
n
-
1
)
&
n
)
==
0
)
if
(((
n
-
1
)
&
n
)
==
0
)
return
n
;
/* Already Power of two. */
return
n
;
/* Already Power of two. */
while
(
n
>
0
)
while
(
n
>
0
)
{
{
n
=
n
>>
1
;
n
=
n
>>
1
;
numBits
++
;
numBits
++
;
}
}
return
(
1
<<
numBits
);
return
(
1
<<
numBits
);
}
}
/************************************************************
/************************************************************
* Opens a PortAudio stream with default characteristics.
* Opens a PortAudio stream with default characteristics.
* Allocates PABLIO_Stream structure.
* Allocates PABLIO_Stream structure.
*
*
* flags parameter can be an ORed combination of:
* flags parameter can be an ORed combination of:
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
* and either PABLIO_MONO or PABLIO_STEREO
*/
*/
PaError
OpenAudioStream
(
PABLIO_Stream
**
rwblPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
PaError
OpenAudioStream
(
PABLIO_Stream
**
rwblPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
)
int
outdev
)
{
{
l
ong
bytesPerSample
;
long
bytesPerSample
;
l
ong
doRead
=
0
;
long
doRead
=
0
;
l
ong
doWrite
=
0
;
long
doWrite
=
0
;
P
aError
err
;
PaError
err
;
P
ABLIO_Stream
*
aStream
;
PABLIO_Stream
*
aStream
;
l
ong
minNumBuffers
;
long
minNumBuffers
;
l
ong
numFrames
;
long
numFrames
;
/* Allocate PABLIO_Stream structure for caller. */
/* Allocate PABLIO_Stream structure for caller. */
aStream
=
(
PABLIO_Stream
*
)
malloc
(
sizeof
(
PABLIO_Stream
));
aStream
=
(
PABLIO_Stream
*
)
malloc
(
sizeof
(
PABLIO_Stream
));
i
f
(
aStream
==
NULL
)
if
(
aStream
==
NULL
)
return
paInsufficientMemory
;
return
paInsufficientMemory
;
m
emset
(
aStream
,
0
,
sizeof
(
PABLIO_Stream
));
memset
(
aStream
,
0
,
sizeof
(
PABLIO_Stream
));
/* Determine size of a sample. */
/* Determine size of a sample. */
bytesPerSample
=
Pa_GetSampleSize
(
format
);
bytesPerSample
=
Pa_GetSampleSize
(
format
);
i
f
(
bytesPerSample
<
0
)
if
(
bytesPerSample
<
0
)
{
{
e
rr
=
(
PaError
)
bytesPerSample
;
err
=
(
PaError
)
bytesPerSample
;
g
oto
error
;
goto
error
;
}
}
a
Stream
->
samplesPerFrame
=
((
flags
&
PABLIO_MONO
)
!=
0
)
?
1
:
2
;
aStream
->
samplesPerFrame
=
((
flags
&
PABLIO_MONO
)
!=
0
)
?
1
:
2
;
a
Stream
->
bytesPerFrame
=
bytesPerSample
*
aStream
->
samplesPerFrame
;
aStream
->
bytesPerFrame
=
bytesPerSample
*
aStream
->
samplesPerFrame
;
/* Initialize PortAudio */
/* Initialize PortAudio */
err
=
Pa_Initialize
();
err
=
Pa_Initialize
();
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
goto
error
;
/* Warning: numFrames must be larger than amount of data processed per interrupt
/* Warning: numFrames must be larger than amount of data processed per interrupt
* inside PA to prevent glitches. Just to be safe, adjust size upwards.
* inside PA to prevent glitches. Just to be safe, adjust size upwards.
*/
*/
minNumBuffers
=
2
*
Pa_GetMinNumBuffers
(
FRAMES_PER_BUFFER
,
sampleRate
);
minNumBuffers
=
2
*
Pa_GetMinNumBuffers
(
FRAMES_PER_BUFFER
,
sampleRate
);
n
umFrames
=
minNumBuffers
*
FRAMES_PER_BUFFER
;
numFrames
=
minNumBuffers
*
FRAMES_PER_BUFFER
;
/* The PortAudio callback runs in a high priority thread. But PABLIO
/* The PortAudio callback runs in a high priority thread. But PABLIO
* runs in a normal foreground thread. So we may have much worse
* runs in a normal foreground thread. So we may have much worse
* latency in PABLIO. So adjust latency to a safe level.
* latency in PABLIO. So adjust latency to a safe level.
*/
*/
{
{
c
onst
int
safeLatencyMSec
=
200
;
const
int
safeLatencyMSec
=
200
;
i
nt
minLatencyMSec
=
(
int
)
((
1000
*
numFrames
)
/
sampleRate
);
int
minLatencyMSec
=
(
int
)
((
1000
*
numFrames
)
/
sampleRate
);
i
f
(
minLatencyMSec
<
safeLatencyMSec
)
if
(
minLatencyMSec
<
safeLatencyMSec
)
{
{
n
umFrames
=
(
int
)
((
safeLatencyMSec
*
sampleRate
)
/
1000
);
numFrames
=
(
int
)
((
safeLatencyMSec
*
sampleRate
)
/
1000
);
}
}
}
nu
mFrames
=
RoundUpToNextPowerOf2
(
numFrames
);
}
numFrames
=
RoundUpToNextPowerOf2
(
numFrames
);
/* Initialize Ring Buffers */
/* Initialize Ring Buffers */
doRead
=
((
flags
&
PABLIO_READ
)
!=
0
);
doRead
=
((
flags
&
PABLIO_READ
)
!=
0
);
d
oWrite
=
((
flags
&
PABLIO_WRITE
)
!=
0
);
doWrite
=
((
flags
&
PABLIO_WRITE
)
!=
0
);
i
f
(
doRead
)
if
(
doRead
)
{
{
e
rr
=
PABLIO_InitFIFO
(
&
aStream
->
inFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
err
=
PABLIO_InitFIFO
(
&
aStream
->
inFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
goto
error
;
}
}
i
f
(
doWrite
)
if
(
doWrite
)
{
{
l
ong
numBytes
;
long
numBytes
;
e
rr
=
PABLIO_InitFIFO
(
&
aStream
->
outFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
err
=
PABLIO_InitFIFO
(
&
aStream
->
outFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
goto
error
;
/* Make Write FIFO appear full initially. */
/* Make Write FIFO appear full initially. */
numBytes
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
numBytes
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
R
ingBuffer_AdvanceWriteIndex
(
&
aStream
->
outFIFO
,
numBytes
);
RingBuffer_AdvanceWriteIndex
(
&
aStream
->
outFIFO
,
numBytes
);
}
}
/* Open a PortAudio stream that we will use to communicate with the underlying
/* Open a PortAudio stream that we will use to communicate with the underlying
* audio drivers. */
* audio drivers. */
err
=
Pa_OpenStream
(
&
aStream
->
stream
,
err
=
Pa_OpenStream
(
&
aStream
->
stream
,
(
doRead
?
(
indev
>
-
1
)
?
indev
:
Pa_GetDefaultInputDeviceID
()
:
paNoDevice
),
(
doRead
?
(
indev
>
-
1
)
?
indev
:
Pa_GetDefaultInputDeviceID
()
:
paNoDevice
),
(
doRead
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
(
doRead
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
(
doWrite
?
(
outdev
>
-
1
)
?
outdev
:
Pa_GetDefaultOutputDeviceID
()
:
paNoDevice
),
(
doWrite
?
(
outdev
>
-
1
)
?
outdev
:
Pa_GetDefaultOutputDeviceID
()
:
paNoDevice
),
(
doWrite
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
sampleRate
,
FRAM
ES_PER_BUFFER
,
(
doWrite
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
sampleRate
,
FRAMES_PER_BUFFER
,
minNumBuffers
,
pa
ClipOff
,
minNumBuffers
,
paClipOff
,
/* we won't output out of range samples so don't bother clipping them */
/* we won't output out of range samples so don't bother clipping them */
blockingIOCallback
,
a
Stream
);
blockingIOCallback
,
aStream
);
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
goto
error
;
e
rr
=
Pa_StartStream
(
aStream
->
stream
);
err
=
Pa_StartStream
(
aStream
->
stream
);
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
goto
error
;
*
rwblPtr
=
aStream
;
*
rwblPtr
=
aStream
;
return
paNoError
;
return
paNoError
;
error:
CloseAudioStream
(
aStream
);
error:
CloseAudioStream
(
aStream
);
*
rwblPtr
=
NULL
;
*
rwblPtr
=
NULL
;
return
err
;
return
err
;
}
}
/************************************************************/
/************************************************************/
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
)
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
)
{
{
P
aError
err
=
paNoError
;
PaError
err
=
paNoError
;
i
nt
bytesEmpty
;
int
bytesEmpty
;
i
nt
byteSize
=
aStream
->
outFIFO
.
bufferSize
;
int
byteSize
=
aStream
->
outFIFO
.
bufferSize
;
i
f
(
aStream
->
stream
!=
NULL
)
/* Make sure stream was opened. PLB021214 */
if
(
aStream
->
stream
!=
NULL
)
/* Make sure stream was opened. PLB021214 */
{
{
/* If we are writing data, make sure we play everything written. */
/* If we are writing data, make sure we play everything written. */
if
(
byteSize
>
0
)
if
(
byteSize
>
0
)
{
{
i
nt
timeOutMSec
=
2000
;
int
timeOutMSec
=
2000
;
b
ytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
w
hile
((
bytesEmpty
<
byteSize
)
&&
(
timeOutMSec
>
0
))
while
((
bytesEmpty
<
byteSize
)
&&
(
timeOutMSec
>
0
))
{
{
P
a_Sleep
(
20
);
Pa_Sleep
(
20
);
t
imeOutMSec
-=
20
;
timeOutMSec
-=
20
;
b
ytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
}
}
}
}
e
rr
=
Pa_StopStream
(
aStream
->
stream
);
err
=
Pa_StopStream
(
aStream
->
stream
);
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
goto
error
;
err
=
Pa_CloseStream
(
aStream
->
stream
);
err
=
Pa_CloseStream
(
aStream
->
stream
);
}
}
error:
Pa_Terminate
();
error:
Pa_Terminate
();
PABLIO_TermFIFO
(
&
aStream
->
inFIFO
);
PABLIO_TermFIFO
(
&
aStream
->
inFIFO
);
PABLIO_TermFIFO
(
&
aStream
->
outFIFO
);
PABLIO_TermFIFO
(
&
aStream
->
outFIFO
);
free
(
aStream
);
free
(
aStream
);
return
err
;
return
err
;
}
}
src/mod/endpoints/mod_portaudio/pablio.h
浏览文件 @
df1f3209
#ifndef _PABLIO_H
#ifndef _PABLIO_H
#define _PABLIO_H
#define _PABLIO_H
#ifdef __cplusplus
#ifdef __cplusplus
extern
"C"
extern
"C"
{
{
#endif
/* __cplusplus */
#endif
/* __cplusplus */
/*
/*
* $Id: pablio.h,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* $Id: pablio.h,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* PABLIO.h
* PABLIO.h
* Portable Audio Blocking read/write utility.
* Portable Audio Blocking read/write utility.
*
*
* Author: Phil Burk, http://www.softsynth.com/portaudio/
* Author: Phil Burk, http://www.softsynth.com/portaudio/
*
*
* Include file for PABLIO, the Portable Audio Blocking I/O Library.
* Include file for PABLIO, the Portable Audio Blocking I/O Library.
* PABLIO is built on top of PortAudio, the Portable Audio Library.
* PABLIO is built on top of PortAudio, the Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* included in all copies or substantial portions of the Software.
*
*
* Any person wishing to distribute modifications to the Software is
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
* they can be incorporated into the canonical version.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
#include <math.h>
#include "portaudio.h"
#include "portaudio.h"
#include "ringbuffer.h"
#include "ringbuffer.h"
#include <string.h>
#include <string.h>
typedef
struct
typedef
struct
{
{
RingBuffer
inFIFO
;
RingBuffer
inFIFO
;
RingBuffer
outFIFO
;
RingBuffer
outFIFO
;
PortAudioStream
*
stream
;
PortAudioStream
*
stream
;
int
bytesPerFrame
;
int
bytesPerFrame
;
int
samplesPerFrame
;
int
samplesPerFrame
;
}
}
PABLIO_Stream
;
PABLIO_Stream
;
/* Values for flags for OpenAudioStream(). */
/* Values for flags for OpenAudioStream(). */
#define PABLIO_READ (1<<0)
#define PABLIO_READ (1<<0)
#define PABLIO_WRITE (1<<1)
#define PABLIO_WRITE (1<<1)
#define PABLIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
#define PABLIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
#define PABLIO_MONO (1<<2)
#define PABLIO_MONO (1<<2)
#define PABLIO_STEREO (1<<3)
#define PABLIO_STEREO (1<<3)
/************************************************************
/************************************************************
* Write data to ring buffer.
* Write data to ring buffer.
* Will not return until all the data has been written.
* Will not return until all the data has been written.
*/
*/
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
/************************************************************
/************************************************************
* Read data from ring buffer.
* Read data from ring buffer.
* Will not return until all the data has been read.
* Will not return until all the data has been read.
*/
*/
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
/************************************************************
/************************************************************
* Return the number of frames that could be written to the stream without
* Return the number of frames that could be written to the stream without
* having to wait.
* having to wait.
*/
*/
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
);
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
);
/************************************************************
/************************************************************
* Return the number of frames that are available to be read from the
* Return the number of frames that are available to be read from the
* stream without having to wait.
* stream without having to wait.
*/
*/
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
);
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
);
/************************************************************
/************************************************************
* Opens a PortAudio stream with default characteristics.
* Opens a PortAudio stream with default characteristics.
* Allocates PABLIO_Stream structure.
* Allocates PABLIO_Stream structure.
*
*
* flags parameter can be an ORed combination of:
* flags parameter can be an ORed combination of:
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
* and either PABLIO_MONO or PABLIO_STEREO
*/
*/
PaError
OpenAudioStream
(
PABLIO_Stream
**
aStreamPtr
,
double
sampleRate
,
PaError
OpenAudioStream
(
PABLIO_Stream
**
aStreamPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
);
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
);
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
);
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
);
#ifdef __cplusplus
#ifdef __cplusplus
}
}
#endif
/* __cplusplus */
#endif
/* __cplusplus */
#endif
/* _PABLIO_H */
#endif
/* _PABLIO_H */
src/mod/endpoints/mod_portaudio/ringbuffer.c
浏览文件 @
df1f3209
/*
/*
* $Id: ringbuffer.c,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* $Id: ringbuffer.c,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* ringbuffer.c
* ringbuffer.c
* Ring Buffer utility..
* Ring Buffer utility..
*
*
* Author: Phil Burk, http://www.softsynth.com
* Author: Phil Burk, http://www.softsynth.com
*
*
* This program uses the PortAudio Portable Audio Library.
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* included in all copies or substantial portions of the Software.
*
*
* Any person wishing to distribute modifications to the Software is
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
* they can be incorporated into the canonical version.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
#include <math.h>
#include "ringbuffer.h"
#include "ringbuffer.h"
#include <string.h>
#include <string.h>
/***************************************************************************
/***************************************************************************
* Initialize FIFO.
* Initialize FIFO.
* numBytes must be power of 2, returns -1 if not.
* numBytes must be power of 2, returns -1 if not.
*/
*/
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
)
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
)
{
{
i
f
(((
numBytes
-
1
)
&
numBytes
)
!=
0
)
if
(((
numBytes
-
1
)
&
numBytes
)
!=
0
)
return
-
1
;
/* Not Power of two. */
return
-
1
;
/* Not Power of two. */
r
buf
->
bufferSize
=
numBytes
;
rbuf
->
bufferSize
=
numBytes
;
r
buf
->
buffer
=
(
char
*
)
dataPtr
;
rbuf
->
buffer
=
(
char
*
)
dataPtr
;
R
ingBuffer_Flush
(
rbuf
);
RingBuffer_Flush
(
rbuf
);
r
buf
->
bigMask
=
(
numBytes
*
2
)
-
1
;
rbuf
->
bigMask
=
(
numBytes
*
2
)
-
1
;
r
buf
->
smallMask
=
(
numBytes
)
-
1
;
rbuf
->
smallMask
=
(
numBytes
)
-
1
;
r
eturn
0
;
return
0
;
}
}
/***************************************************************************
/***************************************************************************
** Return number of bytes available for reading. */
** Return number of bytes available for reading. */
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
)
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
)
{
{
r
eturn
((
rbuf
->
writeIndex
-
rbuf
->
readIndex
)
&
rbuf
->
bigMask
);
return
((
rbuf
->
writeIndex
-
rbuf
->
readIndex
)
&
rbuf
->
bigMask
);
}
}
/***************************************************************************
/***************************************************************************
** Return number of bytes available for writing. */
** Return number of bytes available for writing. */
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
)
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
)
{
{
return
(
rbuf
->
bufferSize
-
RingBuffer_GetReadAvailable
(
rbuf
));
return
(
rbuf
->
bufferSize
-
RingBuffer_GetReadAvailable
(
rbuf
));
}
}
/***************************************************************************
/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
** Clear buffer. Should only be called when buffer is NOT being read. */
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
)
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
)
{
{
r
buf
->
writeIndex
=
rbuf
->
readIndex
=
0
;
rbuf
->
writeIndex
=
rbuf
->
readIndex
=
0
;
}
}
/***************************************************************************
/***************************************************************************
** Get address of region(s) to which we can write data.
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
** Returns room available to be written or numBytes, whichever is smaller.
*/
*/
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
vo
id
**
dataPtr2
,
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
)
long
*
sizePtr2
)
{
{
l
ong
index
;
long
index
;
l
ong
available
=
RingBuffer_GetWriteAvailable
(
rbuf
);
long
available
=
RingBuffer_GetWriteAvailable
(
rbuf
);
i
f
(
numBytes
>
available
)
if
(
numBytes
>
available
)
numBytes
=
available
;
numBytes
=
available
;
/* Check to see if write is not contiguous. */
/* Check to see if write is not contiguous. */
index
=
rbuf
->
writeIndex
&
rbuf
->
smallMask
;
index
=
rbuf
->
writeIndex
&
rbuf
->
smallMask
;
i
f
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
if
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
{
{
/* Write data in two blocks that wrap the buffer. */
/* Write data in two blocks that wrap the buffer. */
long
firstHalf
=
rbuf
->
bufferSize
-
index
;
long
firstHalf
=
rbuf
->
bufferSize
-
index
;
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
firstHalf
;
*
sizePtr1
=
firstHalf
;
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
sizePtr2
=
numBytes
-
firstHalf
;
*
sizePtr2
=
numBytes
-
firstHalf
;
}
}
else
else
{
{
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
numBytes
;
*
sizePtr1
=
numBytes
;
*
dataPtr2
=
NULL
;
*
dataPtr2
=
NULL
;
*
sizePtr2
=
0
;
*
sizePtr2
=
0
;
}
}
r
eturn
numBytes
;
return
numBytes
;
}
}
/***************************************************************************
/***************************************************************************
*/
*/
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
{
{
r
eturn
rbuf
->
writeIndex
=
(
rbuf
->
writeIndex
+
numBytes
)
&
rbuf
->
bigMask
;
return
rbuf
->
writeIndex
=
(
rbuf
->
writeIndex
+
numBytes
)
&
rbuf
->
bigMask
;
}
}
/***************************************************************************
/***************************************************************************
** Get address of region(s) from which we can read data.
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
** Returns room available to be written or numBytes, whichever is smaller.
*/
*/
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
vo
id
**
dataPtr2
,
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
)
long
*
sizePtr2
)
{
{
l
ong
index
;
long
index
;
l
ong
available
=
RingBuffer_GetReadAvailable
(
rbuf
);
long
available
=
RingBuffer_GetReadAvailable
(
rbuf
);
i
f
(
numBytes
>
available
)
if
(
numBytes
>
available
)
numBytes
=
available
;
numBytes
=
available
;
/* Check to see if read is not contiguous. */
/* Check to see if read is not contiguous. */
index
=
rbuf
->
readIndex
&
rbuf
->
smallMask
;
index
=
rbuf
->
readIndex
&
rbuf
->
smallMask
;
i
f
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
if
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
{
{
/* Write data in two blocks that wrap the buffer. */
/* Write data in two blocks that wrap the buffer. */
long
firstHalf
=
rbuf
->
bufferSize
-
index
;
long
firstHalf
=
rbuf
->
bufferSize
-
index
;
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
firstHalf
;
*
sizePtr1
=
firstHalf
;
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
sizePtr2
=
numBytes
-
firstHalf
;
*
sizePtr2
=
numBytes
-
firstHalf
;
}
}
else
else
{
{
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
numBytes
;
*
sizePtr1
=
numBytes
;
*
dataPtr2
=
NULL
;
*
dataPtr2
=
NULL
;
*
sizePtr2
=
0
;
*
sizePtr2
=
0
;
}
}
r
eturn
numBytes
;
return
numBytes
;
}
}
/***************************************************************************
/***************************************************************************
*/
*/
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
{
{
return
rbuf
->
readIndex
=
(
rbuf
->
readIndex
+
numBytes
)
&
rbuf
->
bigMask
;
return
rbuf
->
readIndex
=
(
rbuf
->
readIndex
+
numBytes
)
&
rbuf
->
bigMask
;
}
}
/***************************************************************************
/***************************************************************************
** Return bytes written. */
** Return bytes written. */
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
{
{
l
ong
size1
,
size2
,
numWritten
;
long
size1
,
size2
,
numWritten
;
v
oid
*
data1
,
*
data2
;
void
*
data1
,
*
data2
;
n
umWritten
=
RingBuffer_GetWriteRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
numWritten
=
RingBuffer_GetWriteRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
i
f
(
size2
>
0
)
if
(
size2
>
0
)
{
{
m
emcpy
(
data1
,
data
,
size1
);
memcpy
(
data1
,
data
,
size1
);
d
ata
=
((
char
*
)
data
)
+
size1
;
data
=
((
char
*
)
data
)
+
size1
;
m
emcpy
(
data2
,
data
,
size2
);
memcpy
(
data2
,
data
,
size2
);
}
}
else
else
{
{
m
emcpy
(
data1
,
data
,
size1
);
memcpy
(
data1
,
data
,
size1
);
}
}
R
ingBuffer_AdvanceWriteIndex
(
rbuf
,
numWritten
);
RingBuffer_AdvanceWriteIndex
(
rbuf
,
numWritten
);
r
eturn
numWritten
;
return
numWritten
;
}
}
/***************************************************************************
/***************************************************************************
** Return bytes read. */
** Return bytes read. */
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
{
{
l
ong
size1
,
size2
,
numRead
;
long
size1
,
size2
,
numRead
;
v
oid
*
data1
,
*
data2
;
void
*
data1
,
*
data2
;
n
umRead
=
RingBuffer_GetReadRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
numRead
=
RingBuffer_GetReadRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
i
f
(
size2
>
0
)
if
(
size2
>
0
)
{
{
m
emcpy
(
data
,
data1
,
size1
);
memcpy
(
data
,
data1
,
size1
);
d
ata
=
((
char
*
)
data
)
+
size1
;
data
=
((
char
*
)
data
)
+
size1
;
m
emcpy
(
data
,
data2
,
size2
);
memcpy
(
data
,
data2
,
size2
);
}
}
else
else
{
{
m
emcpy
(
data
,
data1
,
size1
);
memcpy
(
data
,
data1
,
size1
);
}
}
R
ingBuffer_AdvanceReadIndex
(
rbuf
,
numRead
);
RingBuffer_AdvanceReadIndex
(
rbuf
,
numRead
);
r
eturn
numRead
;
return
numRead
;
}
}
src/mod/endpoints/mod_portaudio/ringbuffer.h
浏览文件 @
df1f3209
#ifndef _RINGBUFFER_H
#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
#define _RINGBUFFER_H
#ifdef __cplusplus
#ifdef __cplusplus
extern
"C"
extern
"C"
{
{
#endif
/* __cplusplus */
#endif
/* __cplusplus */
/*
/*
* $Id: ringbuffer.h,v 1.1.1.1.4.2 2003/04/28 17:45:34 philburk Exp $
* $Id: ringbuffer.h,v 1.1.1.1.4.2 2003/04/28 17:45:34 philburk Exp $
* ringbuffer.h
* ringbuffer.h
* Ring Buffer utility..
* Ring Buffer utility..
*
*
* Author: Phil Burk, http://www.softsynth.com
* Author: Phil Burk, http://www.softsynth.com
*
*
* This program is distributed with the PortAudio Portable Audio Library.
* This program is distributed with the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* included in all copies or substantial portions of the Software.
*
*
* Any person wishing to distribute modifications to the Software is
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
* they can be incorporated into the canonical version.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
*/
#define PortAudioStream PaStream
#define PortAudioStream PaStream
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
#include <math.h>
#include "ringbuffer.h"
#include "ringbuffer.h"
#include <string.h>
#include <string.h>
typedef
struct
typedef
struct
{
{
long
bufferSize
;
/* Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init. */
long
bufferSize
;
/* Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init. */
/* These are declared volatile because they are written by a different thread than the reader. */
/* These are declared volatile because they are written by a different thread than the reader. */
volatile
long
writeIndex
;
/* Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. */
volatile
long
writeIndex
;
/* Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. */
volatile
long
readIndex
;
/* Index of next readable byte. Set by RingBuffer_AdvanceReadIndex. */
volatile
long
readIndex
;
/* Index of next readable byte. Set by RingBuffer_AdvanceReadIndex. */
long
bigMask
;
/* Used for wrapping indices with extra bit to distinguish full/empty. */
long
bigMask
;
/* Used for wrapping indices with extra bit to distinguish full/empty. */
long
smallMask
;
/* Used for fitting indices to buffer. */
long
smallMask
;
/* Used for fitting indices to buffer. */
char
*
buffer
;
char
*
buffer
;
}
}
RingBuffer
;
RingBuffer
;
/*
/*
* Initialize Ring Buffer.
* Initialize Ring Buffer.
* numBytes must be power of 2, returns -1 if not.
* numBytes must be power of 2, returns -1 if not.
*/
*/
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
);
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
);
/* Clear buffer. Should only be called when buffer is NOT being read. */
/* Clear buffer. Should only be called when buffer is NOT being read. */
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
);
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
);
/* Return number of bytes available for writing. */
/* Return number of bytes available for writing. */
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
);
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
);
/* Return number of bytes available for read. */
/* Return number of bytes available for read. */
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
);
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
);
/* Return bytes written. */
/* Return bytes written. */
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
/* Return bytes read. */
/* Return bytes read. */
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
/* Get address of region(s) to which we can write data.
/* Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
** Returns room available to be written or numBytes, whichever is smaller.
*/
*/
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
);
void
**
dataPtr2
,
long
*
sizePtr2
);
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
/* Get address of region(s) from which we can read data.
/* Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be read or numBytes, whichever is smaller.
** Returns room available to be read or numBytes, whichever is smaller.
*/
*/
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
);
void
**
dataPtr2
,
long
*
sizePtr2
);
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
#ifdef __cplusplus
#ifdef __cplusplus
}
}
#endif
/* __cplusplus */
#endif
/* __cplusplus */
#endif
/* _RINGBUFFER_H */
#endif
/* _RINGBUFFER_H */
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论