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 $
* pablio.c
* Portable Audio Blocking Input/Output utility.
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/* History:
* PLB021214 - check for valid stream in CloseAudioStream() to prevent hang.
* add timeOutMSec to CloseAudioStream() to prevent hang.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#include "ringbuffer.h"
#include "pablio.h"
#include <string.h>
/************************************************************************/
/******** Constants *****************************************************/
/************************************************************************/
#define FRAMES_PER_BUFFER (256)
/************************************************************************/
/******** Prototypes ****************************************************/
/************************************************************************/
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
un
signed
long
framesPerBuffer
,
P
aTimestamp
outTime
,
void
*
userData
);
s
tatic
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
);
s
tatic
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
);
/************************************************************************/
/******** Functions *****************************************************/
/************************************************************************/
/* Called from PortAudio.
* Read and write data only if there is room in FIFOs.
*/
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
u
nsigned
long
framesPerBuffer
,
PaTimestamp
outTime
,
void
*
userData
)
/*
* $Id: pablio.c,v 1.1.1.1.4.4 2003/03/13 17:28:33 philburk Exp $
* pablio.c
* Portable Audio Blocking Input/Output utility.
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/* History:
* PLB021214 - check for valid stream in CloseAudioStream() to prevent hang.
* add timeOutMSec to CloseAudioStream() to prevent hang.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#include "ringbuffer.h"
#include "pablio.h"
#include <string.h>
/************************************************************************/
/******** Constants *****************************************************/
/************************************************************************/
#define FRAMES_PER_BUFFER (256)
/************************************************************************/
/******** Prototypes ****************************************************/
/************************************************************************/
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
unsigned
long
framesPerBuffer
,
PaTimestamp
outTime
,
void
*
userData
);
static
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
);
static
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
);
/************************************************************************/
/******** Functions *****************************************************/
/************************************************************************/
/* Called from PortAudio.
* Read and write data only if there is room in FIFOs.
*/
static
int
blockingIOCallback
(
void
*
inputBuffer
,
void
*
outputBuffer
,
unsigned
long
framesPerBuffer
,
PaTimestamp
outTime
,
void
*
userData
)
{
P
ABLIO_Stream
*
data
=
(
PABLIO_Stream
*
)
userData
;
l
ong
numBytes
=
data
->
bytesPerFrame
*
framesPerBuffer
;
(
void
)
outTime
;
/* This may get called with NULL inputBuffer during initial setup. */
PABLIO_Stream
*
data
=
(
PABLIO_Stream
*
)
userData
;
long
numBytes
=
data
->
bytesPerFrame
*
framesPerBuffer
;
(
void
)
outTime
;
/* This may get called with NULL inputBuffer during initial setup. */
if
(
inputBuffer
!=
NULL
)
{
R
ingBuffer_Write
(
&
data
->
inFIFO
,
inputBuffer
,
numBytes
);
}
i
f
(
outputBuffer
!=
NULL
)
{
i
nt
i
;
i
nt
numRead
=
RingBuffer_Read
(
&
data
->
outFIFO
,
outputBuffer
,
numBytes
);
/* Zero out remainder of buffer if we run out of data. */
{
RingBuffer_Write
(
&
data
->
inFIFO
,
inputBuffer
,
numBytes
);
}
if
(
outputBuffer
!=
NULL
)
{
int
i
;
int
numRead
=
RingBuffer_Read
(
&
data
->
outFIFO
,
outputBuffer
,
numBytes
);
/* Zero out remainder of buffer if we run out of data. */
for
(
i
=
numRead
;
i
<
numBytes
;
i
++
)
{
((
char
*
)
outputBuffer
)[
i
]
=
0
;
}
}
return
0
;
}
{
((
char
*
)
outputBuffer
)[
i
]
=
0
;
}
}
return
0
;
}
/* Allocate buffer. */
static
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
)
/* Allocate buffer. */
static
PaError
PABLIO_InitFIFO
(
RingBuffer
*
rbuf
,
long
numFrames
,
long
bytesPerFrame
)
{
l
ong
numBytes
=
numFrames
*
bytesPerFrame
;
c
har
*
buffer
=
(
char
*
)
malloc
(
numBytes
);
i
f
(
buffer
==
NULL
)
long
numBytes
=
numFrames
*
bytesPerFrame
;
char
*
buffer
=
(
char
*
)
malloc
(
numBytes
);
if
(
buffer
==
NULL
)
return
paInsufficientMemory
;
memset
(
buffer
,
0
,
numBytes
);
return
(
PaError
)
RingBuffer_Init
(
rbuf
,
numBytes
,
buffer
);
}
memset
(
buffer
,
0
,
numBytes
);
return
(
PaError
)
RingBuffer_Init
(
rbuf
,
numBytes
,
buffer
);
}
/* Free buffer. */
static
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
)
/* Free buffer. */
static
PaError
PABLIO_TermFIFO
(
RingBuffer
*
rbuf
)
{
i
f
(
rbuf
->
buffer
)
if
(
rbuf
->
buffer
)
free
(
rbuf
->
buffer
);
r
buf
->
buffer
=
NULL
;
r
eturn
paNoError
;
}
rbuf
->
buffer
=
NULL
;
return
paNoError
;
}
/************************************************************
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
/************************************************************
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
{
l
ong
bytesWritten
;
c
har
*
p
=
(
char
*
)
data
;
l
ong
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
w
hile
(
numBytes
>
0
)
{
b
ytesWritten
=
RingBuffer_Write
(
&
aStream
->
outFIFO
,
p
,
numBytes
);
n
umBytes
-=
bytesWritten
;
p
+=
bytesWritten
;
i
f
(
numBytes
>
0
)
long
bytesWritten
;
char
*
p
=
(
char
*
)
data
;
long
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
while
(
numBytes
>
0
)
{
bytesWritten
=
RingBuffer_Write
(
&
aStream
->
outFIFO
,
p
,
numBytes
);
numBytes
-=
bytesWritten
;
p
+=
bytesWritten
;
if
(
numBytes
>
0
)
Pa_Sleep
(
10
);
}
return
numFrames
;
}
}
return
numFrames
;
}
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
)
{
l
ong
bytesRead
;
c
har
*
p
=
(
char
*
)
data
;
l
ong
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
w
hile
(
numBytes
>
0
)
{
b
ytesRead
=
RingBuffer_Read
(
&
aStream
->
inFIFO
,
p
,
numBytes
);
n
umBytes
-=
bytesRead
;
p
+=
bytesRead
;
i
f
(
numBytes
>
0
)
long
bytesRead
;
char
*
p
=
(
char
*
)
data
;
long
numBytes
=
aStream
->
bytesPerFrame
*
numFrames
;
while
(
numBytes
>
0
)
{
bytesRead
=
RingBuffer_Read
(
&
aStream
->
inFIFO
,
p
,
numBytes
);
numBytes
-=
bytesRead
;
p
+=
bytesRead
;
if
(
numBytes
>
0
)
Pa_Sleep
(
10
);
}
return
numFrames
;
}
}
return
numFrames
;
}
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
)
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
)
{
i
nt
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
r
eturn
bytesEmpty
/
aStream
->
bytesPerFrame
;
}
int
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
return
bytesEmpty
/
aStream
->
bytesPerFrame
;
}
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
)
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
)
{
int
bytesFull
=
RingBuffer_GetReadAvailable
(
&
aStream
->
inFIFO
);
return
bytesFull
/
aStream
->
bytesPerFrame
;
}
int
bytesFull
=
RingBuffer_GetReadAvailable
(
&
aStream
->
inFIFO
);
return
bytesFull
/
aStream
->
bytesPerFrame
;
}
/************************************************************/
static
unsigned
long
RoundUpToNextPowerOf2
(
unsigned
long
n
)
/************************************************************/
static
unsigned
long
RoundUpToNextPowerOf2
(
unsigned
long
n
)
{
l
ong
numBits
=
0
;
i
f
(((
n
-
1
)
&
n
)
==
0
)
long
numBits
=
0
;
if
(((
n
-
1
)
&
n
)
==
0
)
return
n
;
/* Already Power of two. */
while
(
n
>
0
)
{
n
=
n
>>
1
;
numBits
++
;
}
return
(
1
<<
numBits
);
}
while
(
n
>
0
)
{
n
=
n
>>
1
;
numBits
++
;
}
return
(
1
<<
numBits
);
}
/************************************************************
* Opens a PortAudio stream with default characteristics.
* Allocates PABLIO_Stream structure.
*
* flags parameter can be an ORed combination of:
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
*/
PaError
OpenAudioStream
(
PABLIO_Stream
**
rwblPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
)
/************************************************************
* Opens a PortAudio stream with default characteristics.
* Allocates PABLIO_Stream structure.
*
* flags parameter can be an ORed combination of:
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
*/
PaError
OpenAudioStream
(
PABLIO_Stream
**
rwblPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
)
{
l
ong
bytesPerSample
;
l
ong
doRead
=
0
;
l
ong
doWrite
=
0
;
P
aError
err
;
P
ABLIO_Stream
*
aStream
;
l
ong
minNumBuffers
;
l
ong
numFrames
;
/* Allocate PABLIO_Stream structure for caller. */
long
bytesPerSample
;
long
doRead
=
0
;
long
doWrite
=
0
;
PaError
err
;
PABLIO_Stream
*
aStream
;
long
minNumBuffers
;
long
numFrames
;
/* Allocate PABLIO_Stream structure for caller. */
aStream
=
(
PABLIO_Stream
*
)
malloc
(
sizeof
(
PABLIO_Stream
));
i
f
(
aStream
==
NULL
)
if
(
aStream
==
NULL
)
return
paInsufficientMemory
;
m
emset
(
aStream
,
0
,
sizeof
(
PABLIO_Stream
));
/* Determine size of a sample. */
memset
(
aStream
,
0
,
sizeof
(
PABLIO_Stream
));
/* Determine size of a sample. */
bytesPerSample
=
Pa_GetSampleSize
(
format
);
i
f
(
bytesPerSample
<
0
)
{
e
rr
=
(
PaError
)
bytesPerSample
;
g
oto
error
;
}
a
Stream
->
samplesPerFrame
=
((
flags
&
PABLIO_MONO
)
!=
0
)
?
1
:
2
;
a
Stream
->
bytesPerFrame
=
bytesPerSample
*
aStream
->
samplesPerFrame
;
/* Initialize PortAudio */
if
(
bytesPerSample
<
0
)
{
err
=
(
PaError
)
bytesPerSample
;
goto
error
;
}
aStream
->
samplesPerFrame
=
((
flags
&
PABLIO_MONO
)
!=
0
)
?
1
:
2
;
aStream
->
bytesPerFrame
=
bytesPerSample
*
aStream
->
samplesPerFrame
;
/* Initialize PortAudio */
err
=
Pa_Initialize
();
i
f
(
err
!=
paNoError
)
if
(
err
!=
paNoError
)
goto
error
;
/* Warning: numFrames must be larger than amount of data processed per interrupt
* inside PA to prevent glitches. Just to be safe, adjust size upwards.
*/
/* Warning: numFrames must be larger than amount of data processed per interrupt
* inside PA to prevent glitches. Just to be safe, adjust size upwards.
*/
minNumBuffers
=
2
*
Pa_GetMinNumBuffers
(
FRAMES_PER_BUFFER
,
sampleRate
);
n
umFrames
=
minNumBuffers
*
FRAMES_PER_BUFFER
;
/* The PortAudio callback runs in a high priority thread. But PABLIO
* runs in a normal foreground thread. So we may have much worse
* latency in PABLIO. So adjust latency to a safe level.
*/
numFrames
=
minNumBuffers
*
FRAMES_PER_BUFFER
;
/* The PortAudio callback runs in a high priority thread. But PABLIO
* runs in a normal foreground thread. So we may have much worse
* latency in PABLIO. So adjust latency to a safe level.
*/
{
c
onst
int
safeLatencyMSec
=
200
;
i
nt
minLatencyMSec
=
(
int
)
((
1000
*
numFrames
)
/
sampleRate
);
i
f
(
minLatencyMSec
<
safeLatencyMSec
)
{
n
umFrames
=
(
int
)
((
safeLatencyMSec
*
sampleRate
)
/
1000
);
}
}
nu
mFrames
=
RoundUpToNextPowerOf2
(
numFrames
);
/* Initialize Ring Buffers */
const
int
safeLatencyMSec
=
200
;
int
minLatencyMSec
=
(
int
)
((
1000
*
numFrames
)
/
sampleRate
);
if
(
minLatencyMSec
<
safeLatencyMSec
)
{
numFrames
=
(
int
)
((
safeLatencyMSec
*
sampleRate
)
/
1000
);
}
}
numFrames
=
RoundUpToNextPowerOf2
(
numFrames
);
/* Initialize Ring Buffers */
doRead
=
((
flags
&
PABLIO_READ
)
!=
0
);
d
oWrite
=
((
flags
&
PABLIO_WRITE
)
!=
0
);
i
f
(
doRead
)
{
e
rr
=
PABLIO_InitFIFO
(
&
aStream
->
inFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
i
f
(
err
!=
paNoError
)
doWrite
=
((
flags
&
PABLIO_WRITE
)
!=
0
);
if
(
doRead
)
{
err
=
PABLIO_InitFIFO
(
&
aStream
->
inFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
if
(
err
!=
paNoError
)
goto
error
;
}
i
f
(
doWrite
)
{
l
ong
numBytes
;
e
rr
=
PABLIO_InitFIFO
(
&
aStream
->
outFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
i
f
(
err
!=
paNoError
)
}
if
(
doWrite
)
{
long
numBytes
;
err
=
PABLIO_InitFIFO
(
&
aStream
->
outFIFO
,
numFrames
,
aStream
->
bytesPerFrame
);
if
(
err
!=
paNoError
)
goto
error
;
/* Make Write FIFO appear full initially. */
/* Make Write FIFO appear full initially. */
numBytes
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
R
ingBuffer_AdvanceWriteIndex
(
&
aStream
->
outFIFO
,
numBytes
);
}
/* Open a PortAudio stream that we will use to communicate with the underlying
* audio drivers. */
err
=
Pa_OpenStream
(
&
aStream
->
stream
,
(
doRead
?
(
indev
>
-
1
)
?
indev
:
Pa_GetDefaultInputDeviceID
()
:
paNoDevice
),
(
doRead
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
(
doWrite
?
(
outdev
>
-
1
)
?
outdev
:
Pa_GetDefaultOutputDeviceID
()
:
paNoDevice
),
(
doWrite
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
sampleRate
,
FRAM
ES_PER_BUFFER
,
minNumBuffers
,
pa
ClipOff
,
/* we won't output out of range samples so don't bother clipping them */
blockingIOCallback
,
a
Stream
);
i
f
(
err
!=
paNoError
)
RingBuffer_AdvanceWriteIndex
(
&
aStream
->
outFIFO
,
numBytes
);
}
/* Open a PortAudio stream that we will use to communicate with the underlying
* audio drivers. */
err
=
Pa_OpenStream
(
&
aStream
->
stream
,
(
doRead
?
(
indev
>
-
1
)
?
indev
:
Pa_GetDefaultInputDeviceID
()
:
paNoDevice
),
(
doRead
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
(
doWrite
?
(
outdev
>
-
1
)
?
outdev
:
Pa_GetDefaultOutputDeviceID
()
:
paNoDevice
),
(
doWrite
?
aStream
->
samplesPerFrame
:
0
),
format
,
NULL
,
sampleRate
,
FRAMES_PER_BUFFER
,
minNumBuffers
,
paClipOff
,
/* we won't output out of range samples so don't bother clipping them */
blockingIOCallback
,
aStream
);
if
(
err
!=
paNoError
)
goto
error
;
e
rr
=
Pa_StartStream
(
aStream
->
stream
);
i
f
(
err
!=
paNoError
)
err
=
Pa_StartStream
(
aStream
->
stream
);
if
(
err
!=
paNoError
)
goto
error
;
*
rwblPtr
=
aStream
;
return
paNoError
;
error:
CloseAudioStream
(
aStream
);
*
rwblPtr
=
NULL
;
return
err
;
}
*
rwblPtr
=
aStream
;
return
paNoError
;
error:
CloseAudioStream
(
aStream
);
*
rwblPtr
=
NULL
;
return
err
;
}
/************************************************************/
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
)
/************************************************************/
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
)
{
P
aError
err
=
paNoError
;
i
nt
bytesEmpty
;
i
nt
byteSize
=
aStream
->
outFIFO
.
bufferSize
;
i
f
(
aStream
->
stream
!=
NULL
)
/* Make sure stream was opened. PLB021214 */
{
/* If we are writing data, make sure we play everything written. */
PaError
err
=
paNoError
;
int
bytesEmpty
;
int
byteSize
=
aStream
->
outFIFO
.
bufferSize
;
if
(
aStream
->
stream
!=
NULL
)
/* Make sure stream was opened. PLB021214 */
{
/* If we are writing data, make sure we play everything written. */
if
(
byteSize
>
0
)
{
i
nt
timeOutMSec
=
2000
;
b
ytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
w
hile
((
bytesEmpty
<
byteSize
)
&&
(
timeOutMSec
>
0
))
{
P
a_Sleep
(
20
);
t
imeOutMSec
-=
20
;
b
ytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
}
}
e
rr
=
Pa_StopStream
(
aStream
->
stream
);
i
f
(
err
!=
paNoError
)
{
int
timeOutMSec
=
2000
;
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
while
((
bytesEmpty
<
byteSize
)
&&
(
timeOutMSec
>
0
))
{
Pa_Sleep
(
20
);
timeOutMSec
-=
20
;
bytesEmpty
=
RingBuffer_GetWriteAvailable
(
&
aStream
->
outFIFO
);
}
}
err
=
Pa_StopStream
(
aStream
->
stream
);
if
(
err
!=
paNoError
)
goto
error
;
err
=
Pa_CloseStream
(
aStream
->
stream
);
}
error:
Pa_Terminate
();
PABLIO_TermFIFO
(
&
aStream
->
inFIFO
);
PABLIO_TermFIFO
(
&
aStream
->
outFIFO
);
free
(
aStream
);
return
err
;
}
err
=
Pa_CloseStream
(
aStream
->
stream
);
}
error:
Pa_Terminate
();
PABLIO_TermFIFO
(
&
aStream
->
inFIFO
);
PABLIO_TermFIFO
(
&
aStream
->
outFIFO
);
free
(
aStream
);
return
err
;
}
src/mod/endpoints/mod_portaudio/pablio.h
浏览文件 @
df1f3209
#ifndef _PABLIO_H
#define _PABLIO_H
#ifdef __cplusplus
extern
"C"
{
#endif
/* __cplusplus */
/*
* $Id: pablio.h,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* PABLIO.h
* Portable Audio Blocking read/write utility.
*
* Author: Phil Burk, http://www.softsynth.com/portaudio/
*
* Include file for PABLIO, the Portable Audio Blocking I/O Library.
* PABLIO is built on top of PortAudio, the Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#include "ringbuffer.h"
#include <string.h>
typedef
struct
{
RingBuffer
inFIFO
;
RingBuffer
outFIFO
;
PortAudioStream
*
stream
;
int
bytesPerFrame
;
int
samplesPerFrame
;
}
PABLIO_Stream
;
/* Values for flags for OpenAudioStream(). */
#define PABLIO_READ (1<<0)
#define PABLIO_WRITE (1<<1)
#define PABLIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
#define PABLIO_MONO (1<<2)
#define PABLIO_STEREO (1<<3)
/************************************************************
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
);
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
);
/************************************************************
* Opens a PortAudio stream with default characteristics.
* Allocates PABLIO_Stream structure.
*
* flags parameter can be an ORed combination of:
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
*/
PaError
OpenAudioStream
(
PABLIO_Stream
**
aStreamPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
);
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
);
#ifdef __cplusplus
}
#endif
/* __cplusplus */
#endif
/* _PABLIO_H */
#ifndef _PABLIO_H
#define _PABLIO_H
#ifdef __cplusplus
extern
"C"
{
#endif
/* __cplusplus */
/*
* $Id: pablio.h,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* PABLIO.h
* Portable Audio Blocking read/write utility.
*
* Author: Phil Burk, http://www.softsynth.com/portaudio/
*
* Include file for PABLIO, the Portable Audio Blocking I/O Library.
* PABLIO is built on top of PortAudio, the Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#include "ringbuffer.h"
#include <string.h>
typedef
struct
{
RingBuffer
inFIFO
;
RingBuffer
outFIFO
;
PortAudioStream
*
stream
;
int
bytesPerFrame
;
int
samplesPerFrame
;
}
PABLIO_Stream
;
/* Values for flags for OpenAudioStream(). */
#define PABLIO_READ (1<<0)
#define PABLIO_WRITE (1<<1)
#define PABLIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
#define PABLIO_MONO (1<<2)
#define PABLIO_STEREO (1<<3)
/************************************************************
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long
WriteAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long
ReadAudioStream
(
PABLIO_Stream
*
aStream
,
void
*
data
,
long
numFrames
);
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long
GetAudioStreamWriteable
(
PABLIO_Stream
*
aStream
);
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long
GetAudioStreamReadable
(
PABLIO_Stream
*
aStream
);
/************************************************************
* Opens a PortAudio stream with default characteristics.
* Allocates PABLIO_Stream structure.
*
* flags parameter can be an ORed combination of:
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
*/
PaError
OpenAudioStream
(
PABLIO_Stream
**
aStreamPtr
,
double
sampleRate
,
PaSampleFormat
format
,
long
flags
,
int
indev
,
int
outdev
);
PaError
CloseAudioStream
(
PABLIO_Stream
*
aStream
);
#ifdef __cplusplus
}
#endif
/* __cplusplus */
#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 $
* ringbuffer.c
* Ring Buffer utility..
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ringbuffer.h"
#include <string.h>
/***************************************************************************
* Initialize FIFO.
* numBytes must be power of 2, returns -1 if not.
*/
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
)
/*
* $Id: ringbuffer.c,v 1.1.1.1 2002/01/22 00:52:53 phil Exp $
* ringbuffer.c
* Ring Buffer utility..
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ringbuffer.h"
#include <string.h>
/***************************************************************************
* Initialize FIFO.
* numBytes must be power of 2, returns -1 if not.
*/
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. */
r
buf
->
bufferSize
=
numBytes
;
r
buf
->
buffer
=
(
char
*
)
dataPtr
;
R
ingBuffer_Flush
(
rbuf
);
r
buf
->
bigMask
=
(
numBytes
*
2
)
-
1
;
r
buf
->
smallMask
=
(
numBytes
)
-
1
;
r
eturn
0
;
}
/***************************************************************************
** Return number of bytes available for reading. */
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
)
rbuf
->
bufferSize
=
numBytes
;
rbuf
->
buffer
=
(
char
*
)
dataPtr
;
RingBuffer_Flush
(
rbuf
);
rbuf
->
bigMask
=
(
numBytes
*
2
)
-
1
;
rbuf
->
smallMask
=
(
numBytes
)
-
1
;
return
0
;
}
/***************************************************************************
** Return number of bytes available for reading. */
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. */
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
)
/***************************************************************************
** Return number of bytes available for writing. */
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. */
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
)
/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
)
{
r
buf
->
writeIndex
=
rbuf
->
readIndex
=
0
;
}
/***************************************************************************
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** 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
*
sizePtr2
)
rbuf
->
writeIndex
=
rbuf
->
readIndex
=
0
;
}
/***************************************************************************
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
)
{
l
ong
index
;
l
ong
available
=
RingBuffer_GetWriteAvailable
(
rbuf
);
i
f
(
numBytes
>
available
)
long
index
;
long
available
=
RingBuffer_GetWriteAvailable
(
rbuf
);
if
(
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
;
i
f
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
{
/* Write data in two blocks that wrap the buffer. */
if
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
{
/* Write data in two blocks that wrap the buffer. */
long
firstHalf
=
rbuf
->
bufferSize
-
index
;
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
firstHalf
;
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
sizePtr2
=
numBytes
-
firstHalf
;
}
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
firstHalf
;
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
sizePtr2
=
numBytes
-
firstHalf
;
}
else
{
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
numBytes
;
*
dataPtr2
=
NULL
;
*
sizePtr2
=
0
;
}
r
eturn
numBytes
;
}
/***************************************************************************
*/
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
{
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
numBytes
;
*
dataPtr2
=
NULL
;
*
sizePtr2
=
0
;
}
return
numBytes
;
}
/***************************************************************************
*/
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
{
r
eturn
rbuf
->
writeIndex
=
(
rbuf
->
writeIndex
+
numBytes
)
&
rbuf
->
bigMask
;
}
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** 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
*
sizePtr2
)
return
rbuf
->
writeIndex
=
(
rbuf
->
writeIndex
+
numBytes
)
&
rbuf
->
bigMask
;
}
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
)
{
l
ong
index
;
l
ong
available
=
RingBuffer_GetReadAvailable
(
rbuf
);
i
f
(
numBytes
>
available
)
long
index
;
long
available
=
RingBuffer_GetReadAvailable
(
rbuf
);
if
(
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
;
i
f
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
{
/* Write data in two blocks that wrap the buffer. */
if
((
index
+
numBytes
)
>
rbuf
->
bufferSize
)
{
/* Write data in two blocks that wrap the buffer. */
long
firstHalf
=
rbuf
->
bufferSize
-
index
;
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
firstHalf
;
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
sizePtr2
=
numBytes
-
firstHalf
;
}
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
firstHalf
;
*
dataPtr2
=
&
rbuf
->
buffer
[
0
];
*
sizePtr2
=
numBytes
-
firstHalf
;
}
else
{
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
numBytes
;
*
dataPtr2
=
NULL
;
*
sizePtr2
=
0
;
}
r
eturn
numBytes
;
}
/***************************************************************************
*/
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
)
{
*
dataPtr1
=
&
rbuf
->
buffer
[
index
];
*
sizePtr1
=
numBytes
;
*
dataPtr2
=
NULL
;
*
sizePtr2
=
0
;
}
return
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. */
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
/***************************************************************************
** Return bytes written. */
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
{
l
ong
size1
,
size2
,
numWritten
;
v
oid
*
data1
,
*
data2
;
n
umWritten
=
RingBuffer_GetWriteRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
i
f
(
size2
>
0
)
{
m
emcpy
(
data1
,
data
,
size1
);
d
ata
=
((
char
*
)
data
)
+
size1
;
m
emcpy
(
data2
,
data
,
size2
);
}
long
size1
,
size2
,
numWritten
;
void
*
data1
,
*
data2
;
numWritten
=
RingBuffer_GetWriteRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
if
(
size2
>
0
)
{
memcpy
(
data1
,
data
,
size1
);
data
=
((
char
*
)
data
)
+
size1
;
memcpy
(
data2
,
data
,
size2
);
}
else
{
m
emcpy
(
data1
,
data
,
size1
);
}
R
ingBuffer_AdvanceWriteIndex
(
rbuf
,
numWritten
);
r
eturn
numWritten
;
}
/***************************************************************************
** Return bytes read. */
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
{
memcpy
(
data1
,
data
,
size1
);
}
RingBuffer_AdvanceWriteIndex
(
rbuf
,
numWritten
);
return
numWritten
;
}
/***************************************************************************
** Return bytes read. */
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
)
{
l
ong
size1
,
size2
,
numRead
;
v
oid
*
data1
,
*
data2
;
n
umRead
=
RingBuffer_GetReadRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
i
f
(
size2
>
0
)
{
m
emcpy
(
data
,
data1
,
size1
);
d
ata
=
((
char
*
)
data
)
+
size1
;
m
emcpy
(
data
,
data2
,
size2
);
}
long
size1
,
size2
,
numRead
;
void
*
data1
,
*
data2
;
numRead
=
RingBuffer_GetReadRegions
(
rbuf
,
numBytes
,
&
data1
,
&
size1
,
&
data2
,
&
size2
);
if
(
size2
>
0
)
{
memcpy
(
data
,
data1
,
size1
);
data
=
((
char
*
)
data
)
+
size1
;
memcpy
(
data
,
data2
,
size2
);
}
else
{
m
emcpy
(
data
,
data1
,
size1
);
}
R
ingBuffer_AdvanceReadIndex
(
rbuf
,
numRead
);
r
eturn
numRead
;
}
{
memcpy
(
data
,
data1
,
size1
);
}
RingBuffer_AdvanceReadIndex
(
rbuf
,
numRead
);
return
numRead
;
}
src/mod/endpoints/mod_portaudio/ringbuffer.h
浏览文件 @
df1f3209
#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
#ifdef __cplusplus
extern
"C"
{
#endif
/* __cplusplus */
/*
* $Id: ringbuffer.h,v 1.1.1.1.4.2 2003/04/28 17:45:34 philburk Exp $
* ringbuffer.h
* Ring Buffer utility..
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program is distributed with the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#define PortAudioStream PaStream
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ringbuffer.h"
#include <string.h>
typedef
struct
{
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. */
volatile
long
writeIndex
;
/* Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. */
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
smallMask
;
/* Used for fitting indices to buffer. */
char
*
buffer
;
}
RingBuffer
;
/*
* Initialize Ring Buffer.
* numBytes must be power of 2, returns -1 if not.
*/
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
);
/* Clear buffer. Should only be called when buffer is NOT being read. */
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
);
/* Return number of bytes available for writing. */
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
);
/* Return number of bytes available for read. */
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
);
/* Return bytes written. */
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
/* Return bytes read. */
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
/* Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
);
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
/* Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be read or numBytes, whichever is smaller.
*/
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
);
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
#ifdef __cplusplus
}
#endif
/* __cplusplus */
#endif
/* _RINGBUFFER_H */
#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
#ifdef __cplusplus
extern
"C"
{
#endif
/* __cplusplus */
/*
* $Id: ringbuffer.h,v 1.1.1.1.4.2 2003/04/28 17:45:34 philburk Exp $
* ringbuffer.h
* Ring Buffer utility..
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program is distributed with the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#define PortAudioStream PaStream
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ringbuffer.h"
#include <string.h>
typedef
struct
{
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. */
volatile
long
writeIndex
;
/* Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. */
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
smallMask
;
/* Used for fitting indices to buffer. */
char
*
buffer
;
}
RingBuffer
;
/*
* Initialize Ring Buffer.
* numBytes must be power of 2, returns -1 if not.
*/
long
RingBuffer_Init
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
*
dataPtr
);
/* Clear buffer. Should only be called when buffer is NOT being read. */
void
RingBuffer_Flush
(
RingBuffer
*
rbuf
);
/* Return number of bytes available for writing. */
long
RingBuffer_GetWriteAvailable
(
RingBuffer
*
rbuf
);
/* Return number of bytes available for read. */
long
RingBuffer_GetReadAvailable
(
RingBuffer
*
rbuf
);
/* Return bytes written. */
long
RingBuffer_Write
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
/* Return bytes read. */
long
RingBuffer_Read
(
RingBuffer
*
rbuf
,
void
*
data
,
long
numBytes
);
/* Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long
RingBuffer_GetWriteRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
);
long
RingBuffer_AdvanceWriteIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
/* Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be read or numBytes, whichever is smaller.
*/
long
RingBuffer_GetReadRegions
(
RingBuffer
*
rbuf
,
long
numBytes
,
void
**
dataPtr1
,
long
*
sizePtr1
,
void
**
dataPtr2
,
long
*
sizePtr2
);
long
RingBuffer_AdvanceReadIndex
(
RingBuffer
*
rbuf
,
long
numBytes
);
#ifdef __cplusplus
}
#endif
/* __cplusplus */
#endif
/* _RINGBUFFER_H */
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论