提交 bbb07474 authored 作者: Anthony Minessale's avatar Anthony Minessale

adding some shit

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@100 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 c104ba36
...@@ -251,4 +251,11 @@ struct switch_application_interface { ...@@ -251,4 +251,11 @@ struct switch_application_interface {
const struct switch_application_interface *next; const struct switch_application_interface *next;
}; };
struct switch_api_interface {
const char *interface_name;
const char *desc;
switch_status (*function)(char *in, char *out, size_t outlen);
const struct switch_api_interface *next;
};
#endif #endif
...@@ -78,6 +78,7 @@ typedef typeof(tv.tv_usec) switch_suseconds_t; ...@@ -78,6 +78,7 @@ typedef typeof(tv.tv_usec) switch_suseconds_t;
#define switch_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags)) #define switch_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags))
#define switch_strlen_zero(s) (s && *s != '\0') ? 0 : 1 #define switch_strlen_zero(s) (s && *s != '\0') ? 0 : 1
#define switch_yield(ms) apr_sleep(ms * 10); apr_thread_yield(); #define switch_yield(ms) apr_sleep(ms * 10); apr_thread_yield();
#define SWITCH_DECLARE_GLOBAL_STRING_FUNC(fname, vname) static void fname(char *string) { if (vname) {free(vname); vname = NULL;}vname = strdup(string);}
SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen); SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen);
SWITCH_DECLARE(switch_status) switch_socket_create_pollfd(switch_pollfd_t *poll, switch_socket_t *sock, unsigned int flags, switch_memory_pool *pool); SWITCH_DECLARE(switch_status) switch_socket_create_pollfd(switch_pollfd_t *poll, switch_socket_t *sock, unsigned int flags, switch_memory_pool *pool);
......
...@@ -42,6 +42,8 @@ static const char modname[] = "mod_portaudio"; ...@@ -42,6 +42,8 @@ static const char modname[] = "mod_portaudio";
static switch_memory_pool *module_pool; static switch_memory_pool *module_pool;
static int running = 1; static int running = 1;
#define SAMPLE_TYPE paInt16
typedef short SAMPLE;
typedef enum { typedef enum {
TFLAG_IO = (1 << 0), TFLAG_IO = (1 << 0),
...@@ -60,9 +62,12 @@ typedef enum { ...@@ -60,9 +62,12 @@ typedef enum {
static struct { static struct {
int debug; int debug;
int port; int port;
char *cid_name;
char *cid_num;
char *dialplan; char *dialplan;
char *soundcard;
unsigned int flags; unsigned int flags;
int indev;
int outdev;
} globals; } globals;
struct private_object { struct private_object {
...@@ -73,31 +78,18 @@ struct private_object { ...@@ -73,31 +78,18 @@ struct private_object {
unsigned char databuf[1024]; unsigned char databuf[1024];
switch_core_session *session; switch_core_session *session;
switch_caller_profile *caller_profile; switch_caller_profile *caller_profile;
unsigned int codec; PaError err;
unsigned int codecs; PABLIO_Stream *audio_in;
switch_mutex_t *mutex; PABLIO_Stream *audio_out;
switch_thread_cond_t *cond; int indev;
int outdev;
}; };
static void set_global_dialplan(char *dialplan) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
{ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name)
if (globals.dialplan) { SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num)
free(globals.dialplan);
globals.dialplan = NULL;
}
globals.dialplan = strdup(dialplan);
}
static void set_global_soundcard(char *soundcard)
{
if (globals.soundcard) {
free(globals.soundcard);
globals.soundcard = NULL;
}
globals.soundcard = strdup(soundcard);
}
static const switch_endpoint_interface channel_endpoint_interface; static const switch_endpoint_interface channel_endpoint_interface;
static switch_status channel_on_init(switch_core_session *session); static switch_status channel_on_init(switch_core_session *session);
...@@ -131,10 +123,6 @@ static switch_status channel_on_init(switch_core_session *session) ...@@ -131,10 +123,6 @@ static switch_status channel_on_init(switch_core_session *session)
switch_set_flag(tech_pvt, TFLAG_IO); switch_set_flag(tech_pvt, TFLAG_IO);
switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_thread_cond_create(&tech_pvt->cond, switch_core_session_get_pool(session));
switch_mutex_lock(tech_pvt->mutex);
/* Move Channel's State Machine to RING */ /* Move Channel's State Machine to RING */
switch_channel_set_state(channel, CS_RING); switch_channel_set_state(channel, CS_RING);
...@@ -187,11 +175,13 @@ static switch_status channel_on_hangup(switch_core_session *session) ...@@ -187,11 +175,13 @@ static switch_status channel_on_hangup(switch_core_session *session)
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
switch_clear_flag(tech_pvt, TFLAG_IO); switch_clear_flag(tech_pvt, TFLAG_IO);
switch_thread_cond_signal(tech_pvt->cond);
switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
CloseAudioStream(tech_pvt->audio_in);
CloseAudioStream(tech_pvt->audio_out);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
...@@ -324,35 +314,21 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra ...@@ -324,35 +314,21 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
int t;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
for(;;) { if ((t = ReadAudioStream(tech_pvt->audio_in, tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_frame))) {
if (switch_test_flag(tech_pvt, TFLAG_IO)) { tech_pvt->read_frame.datalen = t * 2;
switch_thread_cond_wait(tech_pvt->cond, tech_pvt->mutex); tech_pvt->read_frame.samples = t;
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_FALSE;
}
while (switch_test_flag(tech_pvt, TFLAG_IO) && !switch_test_flag(tech_pvt, TFLAG_VOICE)) {
switch_yield(1000);
}
if (switch_test_flag(tech_pvt, TFLAG_IO)) {
switch_clear_flag(tech_pvt, TFLAG_VOICE);
if(!tech_pvt->read_frame.datalen) {
continue;
}
*frame = &tech_pvt->read_frame; *frame = &tech_pvt->read_frame;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
}
break;
}
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
...@@ -377,6 +353,7 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr ...@@ -377,6 +353,7 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
} }
*/ */
WriteAudioStream(tech_pvt->audio_out, (short *)frame->data, (int)(frame->datalen / sizeof(SAMPLE)));
//XXX send voice //XXX send voice
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
...@@ -436,6 +413,8 @@ static const switch_loadable_module_interface channel_module_interface = { ...@@ -436,6 +413,8 @@ static const switch_loadable_module_interface channel_module_interface = {
static int dump_info(void); static int dump_info(void);
static void make_call(char *dest); static void make_call(char *dest);
static switch_status load_config(void);
static int get_dev_by_name(char *name, int in);
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) {
...@@ -445,6 +424,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul ...@@ -445,6 +424,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
} }
Pa_Initialize(); Pa_Initialize();
load_config();
dump_info(); dump_info();
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &channel_module_interface; *interface = &channel_module_interface;
...@@ -473,8 +453,22 @@ static switch_status load_config(void) ...@@ -473,8 +453,22 @@ static switch_status load_config(void)
globals.debug = atoi(val); globals.debug = atoi(val);
} else if (!strcmp(var, "dialplan")) { } else if (!strcmp(var, "dialplan")) {
set_global_dialplan(val); set_global_dialplan(val);
} else if (!strcmp(var, "soundcard")) { } else if (!strcmp(var, "cid_name")) {
set_global_soundcard(val); set_global_cid_name(val);
} else if (!strcmp(var, "cid_num")) {
set_global_cid_num(val);
} else if (!strcmp(var, "indev")) {
if (*val == '#') {
globals.indev = atoi(val+1);
} else {
globals.indev = get_dev_by_name(val, 1);
}
} else if (!strcmp(var, "outdev")) {
if (*val == '#') {
globals.outdev = atoi(val+1);
} else {
globals.outdev = get_dev_by_name(val, 1);
}
} }
} }
} }
...@@ -491,14 +485,9 @@ static switch_status load_config(void) ...@@ -491,14 +485,9 @@ static switch_status load_config(void)
SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
{ {
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "sleep\n");
switch_yield(500000);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "sleep\n");
make_call("1000");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "sleep\n");
switch_yield(50000);
make_call("8888");
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }
...@@ -511,6 +500,31 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void) ...@@ -511,6 +500,31 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
} }
static int get_dev_by_name(char *name, int in)
{
int i;
int numDevices;
const PaDeviceInfo *pdi;
numDevices = Pa_CountDevices();
if( numDevices < 0 ) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
return -2;
}
for( i=0; i<numDevices; i++ ) {
pdi = Pa_GetDeviceInfo( i );
if(strstr(pdi->name, name)) {
if(in && pdi->maxInputChannels) {
return i;
} else if (!in && pdi->maxOutputChannels) {
return i;
}
}
}
return -1;
}
static int dump_info(void) static int dump_info(void)
{ {
...@@ -571,6 +585,8 @@ error: ...@@ -571,6 +585,8 @@ error:
static void make_call(char *dest) static void make_call(char *dest)
{ {
switch_core_session *session; switch_core_session *session;
int sample_rate = 8000;
int codec_ms = 20;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel\n");
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) { if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
...@@ -587,11 +603,10 @@ static void make_call(char *dest) ...@@ -587,11 +603,10 @@ static void make_call(char *dest)
return; return;
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan, globals.dialplan,
"Test This Shit", globals.cid_name,
"1231231234", globals.cid_num,
NULL, NULL,
NULL, NULL,
dest))) { dest))) {
...@@ -604,8 +619,8 @@ static void make_call(char *dest) ...@@ -604,8 +619,8 @@ static void make_call(char *dest)
if (switch_core_codec_init(&tech_pvt->read_codec, if (switch_core_codec_init(&tech_pvt->read_codec,
"L16", "L16",
0, sample_rate,
0, codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) { NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
...@@ -613,8 +628,8 @@ static void make_call(char *dest) ...@@ -613,8 +628,8 @@ static void make_call(char *dest)
} else { } else {
if (switch_core_codec_init(&tech_pvt->write_codec, if (switch_core_codec_init(&tech_pvt->write_codec,
"L16", "L16",
0, sample_rate,
0, codec_ms,
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->read_codec);
...@@ -622,9 +637,29 @@ static void make_call(char *dest) ...@@ -622,9 +637,29 @@ static void make_call(char *dest)
} }
} }
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
tech_pvt->indev = globals.indev;
tech_pvt->outdev = globals.outdev;
if ((tech_pvt->err = OpenAudioStream( &tech_pvt->audio_in, sample_rate, SAMPLE_TYPE, PABLIO_READ | PABLIO_MONO, tech_pvt->indev, -1)) == paNoError) {
if ((tech_pvt->err = OpenAudioStream(&tech_pvt->audio_out, sample_rate, SAMPLE_TYPE, PABLIO_WRITE | PABLIO_MONO, -1, tech_pvt->outdev)) != paNoError) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio out!\n");
CloseAudioStream(tech_pvt->audio_in);
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio in!\n");
}
if (tech_pvt->err == paNoError) {
switch_channel_set_state(channel, CS_INIT); switch_channel_set_state(channel, CS_INIT);
switch_core_session_thread_launch(session); switch_core_session_thread_launch(session);
} else {
switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_session_destroy(&session);
}
} }
} }
\ No newline at end of file
差异被折叠。
#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 */
/*
* $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 )
{
if( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
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 )
{
return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
}
/***************************************************************************
** Return number of bytes available for writing. */
long RingBuffer_GetWriteAvailable( RingBuffer *rbuf )
{
return ( rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf));
}
/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
void RingBuffer_Flush( RingBuffer *rbuf )
{
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 )
{
long index;
long available = RingBuffer_GetWriteAvailable( rbuf );
if( numBytes > available ) numBytes = available;
/* Check to see if write is not contiguous. */
index = rbuf->writeIndex & rbuf->smallMask;
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;
}
else
{
*dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = numBytes;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
return numBytes;
}
/***************************************************************************
*/
long RingBuffer_AdvanceWriteIndex( RingBuffer *rbuf, long numBytes )
{
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 )
{
long index;
long available = RingBuffer_GetReadAvailable( rbuf );
if( numBytes > available ) numBytes = available;
/* Check to see if read is not contiguous. */
index = rbuf->readIndex & rbuf->smallMask;
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;
}
else
{
*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 bytes written. */
long RingBuffer_Write( RingBuffer *rbuf, void *data, long numBytes )
{
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
{
memcpy( data1, data, size1 );
}
RingBuffer_AdvanceWriteIndex( rbuf, numWritten );
return numWritten;
}
/***************************************************************************
** Return bytes read. */
long RingBuffer_Read( RingBuffer *rbuf, void *data, long numBytes )
{
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
{
memcpy( data, data1, size1 );
}
RingBuffer_AdvanceReadIndex( rbuf, numRead );
return numRead;
}
#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.
*
*/
#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 */
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\src\include&quot;;&quot;$(ProjectDir)include&quot;;&quot;$(ProjectDir)..\..\libs\apr\include&quot;;&quot;$(ProjectDir)..\..\libs\portaudio\pa_common&quot;;&quot;$(ProjectDir)..\..\libs\portaudio\pablio&quot;;&quot;$(ProjectDir)..\..\libs\portaudio\pa_win_wmme&quot;" AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\src\include&quot;;&quot;$(ProjectDir)include&quot;;&quot;$(ProjectDir)..\..\libs\apr\include&quot;;&quot;$(ProjectDir)..\..\libs\portaudio\pa_common&quot;;&quot;$(ProjectDir)\..\..\..\src\mod\mod_portaudio&quot;;&quot;$(ProjectDir)..\..\libs\portaudio\pa_win_wmme&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
...@@ -194,11 +194,11 @@ ...@@ -194,11 +194,11 @@
> >
</File> </File>
<File <File
RelativePath="..\..\libs\portaudio\pablio\pablio.c" RelativePath="..\..\src\mod\mod_portaudio\pablio.c"
> >
</File> </File>
<File <File
RelativePath="..\..\libs\portaudio\pablio\ringbuffer.c" RelativePath="..\..\src\mod\mod_portaudio\ringbuffer.c"
> >
</File> </File>
</Filter> </Filter>
...@@ -207,6 +207,14 @@ ...@@ -207,6 +207,14 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd" Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
> >
<File
RelativePath="..\..\src\mod\mod_portaudio\pablio.h"
>
</File>
<File
RelativePath="..\..\src\mod\mod_portaudio\ringbuffer.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Resource Files" Name="Resource Files"
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论