[sipxtapi] r1413 committed - Merged revisions 1200-1202 via svnmerge from ...

2 views
Skip to first unread message

codesite...@google.com

unread,
Jan 15, 2011, 10:01:41 AM1/15/11
to sipxtapi...@googlegroups.com
Revision: 1413
Author: jaroslavl1
Date: Sat Jan 15 07:00:40 2011
Log: Merged revisions 1200-1202 via svnmerge from
https://sipxtapi.googlecode.com/svn/branches/calllib-rewrite

........
r1200 | jaroslavl1 | 2009-01-20 21:18:26 +0100 (Tue, 20 Jan 2009) | 3
lines

Added MpSyncPortAudioStream, and created common superclass
MpPortAudioStreamBase. Speaker/mic audio energy now also works for
synchronous streams.

Fixed broken tests.
........
r1201 | jaroslavl1 | 2009-01-20 22:19:51 +0100 (Tue, 20 Jan 2009) | 1 line

Fixed problem in synchronous stream input volume meter.
........
r1202 | jaroslavl1 | 2009-01-20 22:51:13 +0100 (Tue, 20 Jan 2009) | 1 line

Use dither off instead of clip off for audio streams, as it gives better
subjective feeling when there isn't enough frames.
........

http://code.google.com/p/sipxtapi/source/detail?r=1413

Added:
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpAsyncPortAudioStream.h
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioStreamBase.h
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpSyncPortAudioStream.h
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpAsyncPortAudioStream.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioStreamBase.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpSyncPortAudioStream.cpp
Deleted:
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioStream.h
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioStream.cpp
Modified:
/branches/sipxtapi-3.2.1
/branches/sipxtapi-3.2.1/sipXmediaLib/include/Makefile.am
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpAudioDriverBase.h
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioDriver.h
/branches/sipxtapi-3.2.1/sipXmediaLib/sipXmediaLib-msvc71.vcproj
/branches/sipxtapi-3.2.1/sipXmediaLib/sipXmediaLib-msvc8.vcproj
/branches/sipxtapi-3.2.1/sipXmediaLib/src/Makefile.am
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpAudioDriverManager.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioDriver.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MprFromMic.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MprToSpkr.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpAudioBufTest.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpFlowGraphTest.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpGenericResourceTest.h
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpPortAudioDriverTest.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MprBridgeTest.cpp
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MprToSpkrTest.cpp

=======================================
--- /dev/null
+++
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpAsyncPortAudioStream.h
Sat Jan 15 07:00:40 2011
@@ -0,0 +1,181 @@
+//
+// Copyright (C) 2007 Jaroslav Libak
+//
+// $$
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MpPortAudioStream_h__
+#define MpPortAudioStream_h__
+
+// SYSTEM INCLUDES
+// APPLICATION INCLUDES
+#include <os/OsTime.h>
+#include <utl/UtlBool.h>
+#include <mp/MpPortAudioStreamBase.h>
+#include "portaudio.h"
+
+// DEFINES
+// EXTERNAL FUNCTIONS
+// EXTERNAL VARIABLES
+// CONSTANTS
+// FORWARD DECLARATIONS
+// STRUCTS
+// TYPEDEFS
+// MACROS
+// GLOBAL VARIABLES
+// GLOBAL FUNCTIONS
+
+/**
+* Representation of asynchronous portlib audio stream. For synchronous
streams, it is not
+* needed. Stream can be output/input/full duplex. It is only used for
callback. Callback
+* and main thread share the same buffer using lockless algorithm. The
basis of the algorithm
+* is that each thread writes to its own volatile variable, and reads from
other threads variable.
+* No 2 threads write to the same variable. When writing to buffer, writing
pointer can never
+* exceed or equal reading pointer, and when reading, reading pointer
cannot exceed or equal
+* to writing pointer. Thus threads will always use disjoint memory blocks.
+* Statistics about input/output underflows and overflows are computed and
can be printed if needed.
+*/
+class MpAsyncPortAudioStream : public MpPortAudioStreamBase
+{
+ /* //////////////////////////// PUBLIC
//////////////////////////////////// */
+public:
+ /* ============================ CREATORS
================================== */
+ ///@name Creators
+ //@{
+
+ /// Constructor.
+ MpAsyncPortAudioStream(MpAudioStreamId streamId,
+ int outputChannelCount,
+ int inputChannelCount,
+ MpAudioDriverSampleFormat outputSampleFormat,
+ MpAudioDriverSampleFormat inputSampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer);
+
+ /// Destructor.
+ ~MpAsyncPortAudioStream(void);
+ //@}
+
+ /* ============================ MANIPULATORS
============================== */
+ ///@name Manipulators
+ //@{
+
+ /**
+ * audio callback according to portaudio spec. In user data it receives
+ * pointer to MpPortAudioStream instance
+ */
+ static int streamCallback(const void *input,
+ void *output,
+ unsigned long frameCount,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData );
+
+ /**
+ * Reads given number of frames into buffer. Buffer must be allocated
memory.
+ *
+ * @param buffer Allocated memory to read data into
+ * @param frames Number of frames to read
+ * @returns OS_SUCCESS if successful
+ */
+ virtual OsStatus readStream(void *buffer,
+ unsigned long frames);
+
+ /**
+ * Writes given number of frames into stream from buffer.
+ *
+ * @param buffer Buffer with samples
+ * @param frames Number of frames to write to stream
+ * @returns OS_SUCCESS if successful
+ */
+ virtual OsStatus writeStream(const void *buffer,
+ unsigned long frames);
+
+ /**
+ * Prints overflow/underflow statistics.
+ */
+ void printStatistics();
+
+ /**
+ * Resets internal stream buffers to 0 and resets statistics. Needs to
be done
+ * after stream is stopped or aborted. Not thread safe.
+ */
+ virtual void resetStream();
+
+ //@}
+
+ /* ============================ ACCESSORS
================================= */
+ ///@name Accessors
+ //@{
+ //@}
+ /* ============================ INQUIRY
=================================== */
+ ///@name Inquiry
+ //@{
+ //@}
+
+ /* //////////////////////////// PROTECTED
///////////////////////////////// */
+protected:
+
+ /* //////////////////////////// PRIVATE
/////////////////////////////////// */
+private:
+
+ /// Copy constructor (not implemented for this class)
+ MpAsyncPortAudioStream(const MpAsyncPortAudioStream&
rMpPortAudioStream);
+
+ /// Assignment operator (not implemented for this class)
+ MpAsyncPortAudioStream& operator=(const MpAsyncPortAudioStream& rhs);
+
+ /**
+ * Stream callback of this instance to support multiple streams.
+ */
+ int instanceStreamCallback(const void *input,
+ void *output,
+ unsigned long frameCount,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags);
+
+ /**
+ * Gets maximum bytes that can be copied from input to output pos
without exceeding it.
+ * It is useful when preventing inputPos exceeding outputPos.
+ */
+ int getCopyableBytes(unsigned int inputPos, unsigned int outputPos,
unsigned int maxPos) const;
+
+ /**
+ * Gets actual number of frames in input buffer
+ */
+ int getInputBufferFrameCount();
+
+ /**
+ * Gets actual number of frames in output buffer
+ */
+ int getOutputBufferFrameCount();
+
+ unsigned long m_virtualFramesPerBuffer; ///< only used for initializing
m_inputWritePos and m_outputWritePos
+
+ void* m_pInputBuffer; ///< buffer for storing recorded samples
+ void* m_pOutputBuffer; ///< buffer for storing frames going to speaker
+ unsigned int m_inputBufferSize; ///< size of input buffer
+ unsigned int m_outputBufferSize; ///< size of output buffer
+ volatile unsigned int m_inputWritePos; ///< position in input buffer
for writing
+ volatile unsigned int m_inputReadPos; ///< position in input buffer for
reading
+ volatile unsigned int m_outputWritePos; ///< position in output buffer
for writing
+ volatile unsigned int m_outputReadPos; ///< position in output buffer
for reading
+
+ unsigned int m_outputBufferOverflow;
+ unsigned int m_outputBufferUnderflow;
+ unsigned int m_inputBufferOverflow;
+ unsigned int m_inputBufferUnderflow;
+
+ volatile bool m_inputBufferPrefetchMode; ///< whether input buffer is
in prefetch mode
+ volatile bool m_outputBufferPrefetchMode; ///< whether output buffer is
in prefetch mode
+ unsigned int m_inputPrefetchCount; ///< input buffer latency in frames
+ unsigned int m_outputPrefetchCount; ///< output buffer latency in frames
+
+ bool m_bFrameRecorded; ///< whether at least one frame has been recorded
+ bool m_bFramePushed; ///< whether at least one frame has been pushed
+
+ int m_streamReadWriteCount;
+ int m_callbackCallCount;
+};
+
+#endif // MpPortAudioStream_h__
=======================================
--- /dev/null
+++
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioStreamBase.h
Sat Jan 15 07:00:40 2011
@@ -0,0 +1,136 @@
+//
+// Copyright (C) 2007 Jaroslav Libak
+//
+// $$
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MpPortAudioStreamBase_h__
+#define MpPortAudioStreamBase_h__
+
+// SYSTEM INCLUDES
+// APPLICATION INCLUDES
+#include <os/OsStatus.h>
+#include <utl/UtlDefs.h>
+#include <utl/UtlContainable.h>
+#include "mp/MpAudioDriverDefs.h"
+
+// DEFINES
+#define MIN_PORT_SAMPLE_RATE 200
+
+// MACROS
+// EXTERNAL FUNCTIONS
+// CONSTANTS
+// STRUCTS
+// TYPEDEFS
+// MACROS
+// FORWARD DECLARATIONS
+class MpVolumeMeterBase;
+
+/**
+ * Base class for synchronous and asynchronous port audio streams.
+ */
+class MpPortAudioStreamBase : public UtlContainable
+{
+ /* //////////////////////////// PUBLIC
//////////////////////////////////// */
+public:
+ static const UtlContainableType TYPE; /** < Class type used for runtime
checking */
+
+ /* ============================ CREATORS
================================== */
+
+ /** Constructor */
+ MpPortAudioStreamBase(MpAudioStreamId streamId,
+ int outputChannelCount,
+ int inputChannelCount,
+ MpAudioDriverSampleFormat outputSampleFormat,
+ MpAudioDriverSampleFormat inputSampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer);
+
+ /** Destructor */
+ virtual ~MpPortAudioStreamBase();
+
+ /* ============================ MANIPULATORS
============================== */
+
+ /**
+ * Reads given number of frames into buffer. Buffer must be allocated
memory.
+ *
+ * @param buffer Allocated memory to read data into
+ * @param frames Number of frames to read
+ * @returns OS_SUCCESS if successful
+ */
+ virtual OsStatus readStream(void *buffer,
+ unsigned long frames) = 0;
+
+ /**
+ * Writes given number of frames into stream from buffer.
+ *
+ * @param buffer Buffer with samples
+ * @param frames Number of frames to write to stream
+ * @returns OS_SUCCESS if successful
+ */
+ virtual OsStatus writeStream(const void *buffer,
+ unsigned long frames) = 0;
+
+ /**
+ * Resets internal stream buffers to 0 and resets statistics. Needs to
be done
+ * after stream is stopped or aborted. Not thread safe.
+ */
+ virtual void resetStream();
+
+ /* ============================ ACCESSORS
================================= */
+
+ /**
+ * Calculate a unique hash code for this object. If the equals
+ * operator returns true for another object, then both of those
+ * objects must return the same hashcode.
+ */
+ virtual unsigned hash() const;
+
+ /**
+ * Get the ContainableType for a UtlContainable derived class.
+ */
+ virtual UtlContainableType getContainableType() const;
+
+ /* ============================ INQUIRY
=================================== */
+
+ /**
+ * Compare the this object to another like-objects. Results for
+ * designating a non-like object are undefined.
+ *
+ * @returns 0 if equal, < 0 if less then and >0 if greater.
+ */
+ virtual int compareTo(UtlContainable const* inVal) const;
+
+ /**
+ * Gets volume for input stream calculated from samples.
+ */
+ double getInputStreamVolume(MP_VOLUME_METER_TYPE type) const;
+
+ /**
+ * Gets volume for output stream calculated from samples.
+ */
+ double getOutputStreamVolume(MP_VOLUME_METER_TYPE type) const;
+
+ /* //////////////////////////// PROTECTED
///////////////////////////////// */
+protected:
+
+ MpAudioStreamId m_streamId; ///< internal id of port audio stream
+ int m_outputChannelCount; ///< number of output channels
+ int m_inputChannelCount; ///< number of input channels
+ MpAudioDriverSampleFormat m_outputSampleFormat; ///< sample format of
output
+ MpAudioDriverSampleFormat m_inputSampleFormat; ///< sample format of
input
+ double m_sampleRate; ///< sample rate for stream
+ unsigned long m_framesPerBuffer; ///< frames per buffer for stream
+
+ unsigned int m_inputSampleSize; ///< size of input sample in bytes per
channel
+ unsigned int m_outputSampleSize; ///< size of output sample in bytes
per channel
+
+ MpVolumeMeterBase* m_inputVolumeMeter; ///< volume meter for input
+ MpVolumeMeterBase* m_outputVolumeMeter; ///< volume meter for output
+
+ /* //////////////////////////// PRIVATE
/////////////////////////////////// */
+private:
+
+};
+
+#endif // MpPortAudioStreamBase_h__
=======================================
--- /dev/null
+++
/branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpSyncPortAudioStream.h
Sat Jan 15 07:00:40 2011
@@ -0,0 +1,84 @@
+//
+// Copyright (C) 2004-2006 SIPfoundry Inc.
+// Licensed by SIPfoundry under the LGPL license.
+//
+// Copyright (C) 2004-2006 Pingtel Corp. All rights reserved.
+// Licensed to SIPfoundry under a Contributor Agreement.
+//
+// Copyright (C) 2007 Jaroslav Libak
+// Licensed under the LGPL license.
+// $$
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MpSyncPortAudioStream_h__
+#define MpSyncPortAudioStream_h__
+
+// SYSTEM INCLUDES
+// APPLICATION INCLUDES
+#include <mp/MpPortAudioStreamBase.h>
+
+// DEFINES
+// MACROS
+// EXTERNAL FUNCTIONS
+// CONSTANTS
+// STRUCTS
+// TYPEDEFS
+// MACROS
+// FORWARD DECLARATIONS
+
+/**
+ * This class represents synchronous port audio stream.
+ */
+class MpSyncPortAudioStream : public MpPortAudioStreamBase
+{
+ /* //////////////////////////// PUBLIC
//////////////////////////////////// */
+public:
+ /* ============================ CREATORS
================================== */
+
+ /** Constructor */
+ MpSyncPortAudioStream(MpAudioStreamId streamId,
+ int outputChannelCount,
+ int inputChannelCount,
+ MpAudioDriverSampleFormat outputSampleFormat,
+ MpAudioDriverSampleFormat inputSampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer);
+
+ /** Destructor */
+ virtual ~MpSyncPortAudioStream();
+
+ /* ============================ MANIPULATORS
============================== */
+
+ /**
+ * Reads given number of frames into buffer. Buffer must be allocated
memory.
+ *
+ * @param buffer Allocated memory to read data into
+ * @param frames Number of frames to read
+ * @returns OS_SUCCESS if successful
+ */
+ virtual OsStatus readStream(void *buffer,
+ unsigned long frames);
+
+ /**
+ * Writes given number of frames into stream from buffer.
+ *
+ * @param buffer Buffer with samples
+ * @param frames Number of frames to write to stream
+ * @returns OS_SUCCESS if successful
+ */
+ virtual OsStatus writeStream(const void *buffer,
+ unsigned long frames);
+
+ /* ============================ ACCESSORS
================================= */
+
+ /* ============================ INQUIRY
=================================== */
+
+ /* //////////////////////////// PROTECTED
///////////////////////////////// */
+protected:
+
+ /* //////////////////////////// PRIVATE
/////////////////////////////////// */
+private:
+
+};
+
+#endif // MpSyncPortAudioStream_h__
=======================================
--- /dev/null
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpAsyncPortAudioStream.cpp
Sat Jan 15 07:00:40 2011
@@ -0,0 +1,550 @@
+//
+// Copyright (C) 2007 Jaroslav Libak
+// Licensed under the LGPL license.
+// $$
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef DISABLE_LOCAL_AUDIO
+
+// SYSTEM INCLUDES
+// APPLICATION INCLUDES
+#include <assert.h>
+#include <os/OsIntTypes.h>
+#include <os/OsSysLog.h>
+#include <os/OsDateTime.h>
+#include "mp/MpAsyncPortAudioStream.h"
+#include "mp/MpVolumeMeter.h"
+
+// DEFINES
+//#define DEBUG_AUDIO_STREAM
+#define INPUT_PREFETCH_BUFFERS_COUNT 8
+#define OUTPUT_PREFETCH_BUFFERS_COUNT 8
+
+// EXTERNAL FUNCTIONS
+// EXTERNAL VARIABLES
+// CONSTANTS
+// STATIC VARIABLE INITIALIZATIONS
+// MACROS
+// GLOBAL VARIABLES
+// GLOBAL FUNCTIONS
+
+/* //////////////////////////// PUBLIC
//////////////////////////////////// */
+
+/* ============================ CREATORS
================================== */
+
+MpAsyncPortAudioStream::MpAsyncPortAudioStream(MpAudioStreamId streamId,
+ int outputChannelCount,
+ int inputChannelCount,
+ MpAudioDriverSampleFormat
outputSampleFormat,
+ MpAudioDriverSampleFormat
inputSampleFormat,
+ double sampleRate,
+ unsigned long
framesPerBuffer)
+: MpPortAudioStreamBase(streamId, outputChannelCount, inputChannelCount,
+ outputSampleFormat, inputSampleFormat,
+ sampleRate, framesPerBuffer)
+, m_virtualFramesPerBuffer(0)
+, m_pInputBuffer(NULL)
+, m_pOutputBuffer(NULL)
+, m_inputBufferSize(0)
+, m_outputBufferSize(0)
+, m_inputWritePos(0)
+, m_inputReadPos(0)
+, m_outputWritePos(0)
+, m_outputReadPos(0)
+, m_outputBufferOverflow(0)
+, m_outputBufferUnderflow(0)
+, m_inputBufferOverflow(0)
+, m_inputBufferUnderflow(0)
+, m_inputBufferPrefetchMode(true)
+, m_outputBufferPrefetchMode(true)
+, m_inputPrefetchCount(0)
+, m_outputPrefetchCount(0)
+, m_bFrameRecorded(false)
+, m_bFramePushed(false)
+, m_streamReadWriteCount(0)
+, m_callbackCallCount(0)
+{
+ m_virtualFramesPerBuffer = m_framesPerBuffer;
+
+ if (m_virtualFramesPerBuffer == 0)
+ {
+ // callback will accept frames of any size anyway...
+ // use 160 for now, we need to create buffers of certain size, but
will accept any number of frames
+ m_virtualFramesPerBuffer = 160;
+ }
+
+ // allocate input buffer
+ if (m_inputSampleFormat > 0 && m_inputChannelCount > 0)
+ {
+ unsigned int inputFrameSize = m_inputSampleSize *
m_inputChannelCount;
+ unsigned int inputBufferReserve = ((unsigned int)m_sampleRate /
MIN_PORT_SAMPLE_RATE + 5);
+ m_inputBufferSize = inputFrameSize * m_virtualFramesPerBuffer *
inputBufferReserve;
+ m_inputPrefetchCount = min(INPUT_PREFETCH_BUFFERS_COUNT,
inputBufferReserve) * m_virtualFramesPerBuffer;
+ m_pInputBuffer = malloc(m_inputBufferSize);
+
+ if (!m_pInputBuffer)
+ {
+ // allocation error, don't use buffer
+ m_inputBufferSize = 0;
+ }
+ else
+ {
+ // zero buffer
+ memset(m_pInputBuffer, 0, m_inputBufferSize);
+ // start writing at the next sample position
+ m_inputWritePos = inputFrameSize;
+ }
+ }
+
+ // allocate output buffer
+ if (m_outputSampleSize > 0 && m_outputChannelCount > 0)
+ {
+ unsigned int outputFrameSize = m_outputSampleSize *
m_outputChannelCount;
+ unsigned int outputBufferReserve = ((unsigned int)m_sampleRate /
MIN_PORT_SAMPLE_RATE + 5);
+ m_outputBufferSize = outputFrameSize * m_virtualFramesPerBuffer *
outputBufferReserve;
+ m_outputPrefetchCount = min(OUTPUT_PREFETCH_BUFFERS_COUNT,
outputBufferReserve) * m_virtualFramesPerBuffer;
+ m_pOutputBuffer = malloc(m_outputBufferSize);
+
+ if (!m_pOutputBuffer)
+ {
+ // allocation error, don't use buffer
+ m_outputBufferSize = 0;
+ }
+ else
+ {
+ // zero buffer
+ memset(m_pOutputBuffer, 0, m_outputBufferSize);
+ // start writing at the next sample position
+ m_outputWritePos = outputFrameSize;
+ }
+ }
+}
+
+MpAsyncPortAudioStream::~MpAsyncPortAudioStream(void)
+{
+ if (m_pInputBuffer)
+ {
+ free(m_pInputBuffer);
+ m_pInputBuffer = NULL;
+ }
+
+ if (m_pOutputBuffer)
+ {
+ free(m_pOutputBuffer);
+ m_pOutputBuffer = NULL;
+ }
+}
+
+/* ============================ MANIPULATORS
============================== */
+
+int MpAsyncPortAudioStream::streamCallback(const void *input,
+ void *output,
+ unsigned long frameCount,
+ const PaStreamCallbackTimeInfo*
timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData)
+{
+ if (userData)
+ {
+ MpAsyncPortAudioStream* instance = (MpAsyncPortAudioStream*)userData;
+
+ return instance->instanceStreamCallback(input, output, frameCount,
timeInfo, statusFlags);
+ }
+
+ return paContinue;
+}
+
+OsStatus MpAsyncPortAudioStream::readStream(void *buffer,
+ unsigned long frames)
+{
+ OsStatus status = OS_FAILED;
+
+#ifdef DEBUG_AUDIO_STREAM
+ if (m_bFrameRecorded && m_streamReadWriteCount++ % 200 == 0)
+ {
+ this->printStatistics();
+ }
+#endif
+
+ if (frames > 0 && m_inputSampleSize > 0)
+ {
+ if ((m_framesPerBuffer == 0) || (m_framesPerBuffer == frames))
+ {
+ // count number of required bytes in buffer
+ unsigned int bytesRequired = m_inputSampleSize *
m_inputChannelCount * frames;
+
+ if (m_inputBufferPrefetchMode)
+ {
+ // input is in prefetch mode, send zeroes only
+ memset(buffer, 0, bytesRequired);
+ status = OS_PREFETCH;
+ return status;
+ }
+
+ unsigned int copyable = getCopyableBytes(m_inputReadPos,
m_inputWritePos, m_inputBufferSize);
+ unsigned int bytesToCopy = min(bytesRequired, copyable);
+ unsigned int framesToCopy = bytesToCopy / (m_inputSampleSize *
m_inputChannelCount);
+
+ if (framesToCopy < frames)
+ {
+ // we are out of buffer
+ if (m_bFrameRecorded)
+ {
+ // record underflows only since the 1st frame was recorded
+ m_inputBufferUnderflow++;
+ }
+ status = OS_UNDERFLOW;
+ }
+ else if (framesToCopy == frames)
+ {
+ status = OS_SUCCESS;
+ }
+
+ if (framesToCopy > 0)
+ {
+ unsigned int realBytesToCopy = framesToCopy *
m_inputSampleSize * m_inputChannelCount;
+
+ // count1 is number of bytes to copy before wrapping occurs
+ int count1 = min(realBytesToCopy, m_inputBufferSize -
m_inputReadPos);
+ // count 2 is number of bytes to copy after wrapping
+ int count2 = realBytesToCopy - count1;
+ // now copy some frames
+ memcpy(buffer, (char*)m_pInputBuffer + m_inputReadPos, count1);
+ if (count2 > 0)
+ {
+ // handle wrap around
+ memcpy((char*)buffer + count1, m_pInputBuffer, count2);
+ }
+ m_inputReadPos = (m_inputReadPos + realBytesToCopy) %
m_inputBufferSize;
+ }
+ }
+ }
+
+ return status;
+}
+
+OsStatus MpAsyncPortAudioStream::writeStream(const void *buffer,
+ unsigned long frames)
+{
+ OsStatus status = OS_FAILED;
+
+#ifdef DEBUG_AUDIO_STREAM
+ if (m_bFramePushed && m_streamReadWriteCount++ % 200 == 0)
+ {
+ this->printStatistics();
+ }
+#endif
+
+ if (frames > 0 && m_outputSampleSize > 0)
+ {
+ if ((m_framesPerBuffer == 0) || (m_framesPerBuffer == frames))
+ {
+ // count number of required bytes in buffer
+ unsigned int bytesRequired = m_outputSampleSize *
m_outputChannelCount * frames;
+
+ unsigned int copyable = getCopyableBytes(m_outputWritePos,
m_outputReadPos, m_outputBufferSize);
+ unsigned int bytesToCopy = min(bytesRequired, copyable);
+ unsigned int framesToCopy = bytesToCopy / (m_outputSampleSize *
m_outputChannelCount);
+
+ if (framesToCopy < frames)
+ {
+ // we are out of buffer
+ OsSysLog::add(FAC_AUDIO, PRI_WARNING, "Output stream buffer
overflow!\n");
+ m_outputBufferOverflow++;
+ status = OS_OVERFLOW;
+ }
+ else if (framesToCopy == frames)
+ {
+ status = OS_SUCCESS;
+ }
+
+ if (framesToCopy > 0)
+ {
+ m_bFramePushed = true;
+ unsigned int realBytesToCopy = framesToCopy *
m_outputSampleSize * m_outputChannelCount;
+
+ // count1 is number of bytes to copy before wrapping occurs
+ int count1 = min(realBytesToCopy, m_outputBufferSize -
m_outputWritePos);
+ // count 2 is number of bytes to copy after wrapping
+ int count2 = realBytesToCopy - count1;
+ // now copy some frames
+ memcpy((char*)m_pOutputBuffer + m_outputWritePos, buffer,
count1);
+ if (count2 > 0)
+ {
+ // handle wrap around
+ memcpy(m_pOutputBuffer, (char*)buffer + count1, count2);
+ }
+ m_outputWritePos = (m_outputWritePos + realBytesToCopy) %
m_outputBufferSize;
+ }
+ }
+ }
+
+ return status;
+}
+
+void MpAsyncPortAudioStream::printStatistics()
+{
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"---------
MpPortAudioStream::printStatistics ---------\n");
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_outputBufferOverflow = %d\n",
m_outputBufferOverflow);
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_outputBufferUnderflow = %d\n",
m_outputBufferUnderflow);
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_inputBufferOverflow = %d\n",
m_inputBufferOverflow);
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_inputBufferUnderflow = %d\n",
m_inputBufferUnderflow);
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_streamReadWriteCount = %d\n",
m_streamReadWriteCount);
+ OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_callbackCallCount = %d\n",
m_callbackCallCount);
+ OsSysLog::add(FAC_AUDIO,
PRI_DEBUG,"------------------------------------------------------\n");
+}
+
+void MpAsyncPortAudioStream::resetStream()
+{
+ MpPortAudioStreamBase::resetStream();
+
+ m_inputWritePos = 0;
+ m_inputReadPos = 0;
+ m_outputWritePos = 0;
+ m_outputReadPos = 0;
+
+ // zero buffers
+ if (m_pInputBuffer)
+ {
+ memset(m_pInputBuffer, 0, m_inputBufferSize);
+ m_inputWritePos = m_inputSampleSize * m_inputChannelCount;
+ }
+
+ if (m_pOutputBuffer)
+ {
+ memset(m_pOutputBuffer, 0, m_outputBufferSize);
+ m_outputWritePos = m_outputSampleSize * m_outputChannelCount;
+ }
+
+ // reset statistics
+ m_outputBufferOverflow = 0;
+ m_outputBufferUnderflow = 0;
+ m_inputBufferOverflow = 0;
+ m_inputBufferUnderflow = 0;
+ m_bFrameRecorded = false;
+ m_bFramePushed = false;
+ m_inputBufferPrefetchMode = true;
+ m_outputBufferPrefetchMode = true;
+}
+
+/* ============================ ACCESSORS
================================= */
+
+/* ============================ INQUIRY
=================================== */
+
+/* //////////////////////////// PROTECTED
///////////////////////////////// */
+
+/* //////////////////////////// PRIVATE
/////////////////////////////////// */
+
+int MpAsyncPortAudioStream::instanceStreamCallback(const void *input,
+ void *output,
+ unsigned long
frameCount,
+ const
PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags
statusFlags)
+{
+ // portaudio supplied us pointers to its input and output buffers
+
+#ifdef DEBUG_AUDIO_STREAM
+ if (m_bFrameRecorded || m_bFramePushed)
+ {
+ m_callbackCallCount++;
+ }
+#endif
+
+ if (frameCount > 0)
+ {
+ // handle output frames
+ if (m_outputChannelCount > 0 && output && m_outputSampleSize > 0)
+ {
+ // copy output frames to meter
+ if (m_outputVolumeMeter)
+ {
+ m_outputVolumeMeter->pushBuffer(output, frameCount);
+ }
+
+ unsigned int outputFrameCount = getOutputBufferFrameCount();
+
+ if (m_outputBufferPrefetchMode)
+ {
+ // prefetch is on
+ if (outputFrameCount > m_outputPrefetchCount)
+ {
+ // we have enough frames, disable prefetch mode
+ m_outputBufferPrefetchMode = false;
+ }
+ }
+ else
+ {
+ // prefetch is off
+ if (outputFrameCount <= 0)
+ {
+ // we are out of buffer
+ if (m_bFramePushed)
+ {
+ // record only underflows since the first push
+ m_outputBufferUnderflow++;
+ }
+ // buffer is empty, enable prefetch
+ m_outputBufferPrefetchMode = true;
+ }
+ }
+
+ // count number of required bytes in buffer
+ unsigned int bytesRequired = m_outputSampleSize *
m_outputChannelCount * frameCount;
+
+ unsigned int copyable = 0;
+ if (!m_outputBufferPrefetchMode)
+ {
+ copyable = getCopyableBytes(m_outputReadPos, m_outputWritePos,
m_outputBufferSize);
+ }
+ unsigned int bytesToCopy = min(bytesRequired, copyable);
+ unsigned int framesToCopy = bytesToCopy / (m_outputSampleSize *
m_outputChannelCount);
+ unsigned int zeroFrames = 0;
+
+ if (framesToCopy < frameCount && !m_outputBufferPrefetchMode)
+ {
+ // we will have to copy zeroFrames filled with 0s, as we don't
have enough data
+ zeroFrames = frameCount - framesToCopy;
+ }
+
+ if (framesToCopy > 0)
+ {
+ unsigned int realBytesToCopy = framesToCopy *
m_outputSampleSize * m_outputChannelCount;
+
+ // count1 is number of bytes to copy before wrapping occurs
+ int count1 = min(realBytesToCopy, m_outputBufferSize -
m_outputReadPos);
+ // count 2 is number of bytes to copy after wrapping
+ int count2 = realBytesToCopy - count1;
+ // now copy some frames
+ memcpy(output, (char*)m_pOutputBuffer + m_outputReadPos,
count1);
+ if (count2 > 0)
+ {
+ // handle wrap around
+ memcpy((char*)output + count1, m_pOutputBuffer, count2);
+ }
+
+ // fill zeroFrames with 0s
+ if (zeroFrames > 0)
+ {
+ char* outputBuff = (char*)output + count1 + count2;
+ unsigned int zeroBytesToCopy = zeroFrames *
m_outputSampleSize * m_outputChannelCount;
+ for (unsigned int i = 0; i < zeroBytesToCopy; i++)
+ {
+ *outputBuff++ = 0;
+ }
+ }
+
+ m_outputReadPos = (m_outputReadPos + realBytesToCopy) %
m_outputBufferSize;
+ }
+ else
+ {
+ // prefetch is on, or buffer is empty
+ // output zeros
+ memset(output, 0, bytesRequired);
+ }
+ }
+
+ // handle input frames
+ if (m_inputChannelCount > 0 && input && m_inputSampleSize > 0)
+ {
+ // copy input frames to meter
+ if (m_inputVolumeMeter)
+ {
+ m_inputVolumeMeter->pushBuffer(input, frameCount);
+ }
+
+ unsigned int inputFrameCount = getInputBufferFrameCount();
+
+ if (m_inputBufferPrefetchMode)
+ {
+ // prefetch is on
+ if (inputFrameCount > m_inputPrefetchCount)
+ {
+ // we have enough frames, disable prefetch mode
+ m_inputBufferPrefetchMode = false;
+ }
+ }
+ else
+ {
+ // prefetch is off
+ if (inputFrameCount <= 0)
+ {
+ // buffer is empty, enable prefetch
+ m_inputBufferPrefetchMode = true;
+ }
+ }
+
+ // count number of required bytes in buffer
+ unsigned int bytesRequired = m_inputSampleSize *
m_inputChannelCount * frameCount;
+
+ unsigned int copyable = getCopyableBytes(m_inputWritePos,
m_inputReadPos, m_inputBufferSize);
+ unsigned int bytesToCopy = min(bytesRequired, copyable);
+ unsigned int framesToCopy = bytesToCopy / (m_inputSampleSize *
m_inputChannelCount);
+
+ if (framesToCopy < frameCount)
+ {
+ // we are out of buffer
+ m_inputBufferOverflow++;
+ }
+
+ if (framesToCopy > 0)
+ {
+ m_bFrameRecorded = true;
+ unsigned int realBytesToCopy = framesToCopy *
m_inputSampleSize * m_inputChannelCount;
+
+ // count1 is number of bytes to copy before wrapping occurs
+ int count1 = min(realBytesToCopy, m_inputBufferSize -
m_inputWritePos);
+ // count 2 is number of bytes to copy after wrapping
+ int count2 = realBytesToCopy - count1;
+ // now copy some frames
+ memcpy((char*)m_pInputBuffer + m_inputWritePos, input, count1);
+ if (count2 > 0)
+ {
+ // handle wrap around
+ memcpy(m_pInputBuffer, (char*)input + count1, count2);
+ }
+
+ // advance m_inputWritePos by realBytesToCopy
+ m_inputWritePos = (m_inputWritePos + realBytesToCopy) %
m_inputBufferSize;
+ }
+ }
+ }
+
+ return paContinue;
+}
+
+int MpAsyncPortAudioStream::getCopyableBytes(unsigned int inputPos,
+ unsigned int outputPos,
+ unsigned int maxPos) const
+{
+ if (inputPos < outputPos)
+ {
+ if (inputPos < maxPos && outputPos < maxPos)
+ {
+ return outputPos - inputPos - 1;
+ }
+ }
+ else if (inputPos > outputPos)
+ {
+ if (outputPos < maxPos)
+ {
+ return maxPos - inputPos + outputPos - 1;
+ }
+ }
+
+ return 0;
+}
+
+int MpAsyncPortAudioStream::getInputBufferFrameCount()
+{
+ return getCopyableBytes(m_inputReadPos, m_inputWritePos,
m_inputBufferSize) / (m_inputSampleSize * m_inputChannelCount);
+}
+
+int MpAsyncPortAudioStream::getOutputBufferFrameCount()
+{
+ return getCopyableBytes(m_outputReadPos, m_outputWritePos,
m_outputBufferSize) / (m_outputSampleSize * m_outputChannelCount);
+}
+
+/* ============================ FUNCTIONS
================================= */
+
+
+#endif // DISABLE_LOCAL_AUDIO
=======================================
--- /dev/null
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioStreamBase.cpp
Sat Jan 15 07:00:40 2011
@@ -0,0 +1,216 @@
+//
+// Copyright (C) 2007 Jaroslav Libak
+//
+// $$
+///////////////////////////////////////////////////////////////////////////////
+
+// SYSTEM INCLUDES
+// APPLICATION INCLUDES
+#include <os/OsIntTypes.h>
+#include <os/OsSysLog.h>
+#include <mp/MpPortAudioStreamBase.h>
+#include "mp/MpVolumeMeter.h"
+#include "portaudio.h"
+
+// DEFINES
+// EXTERNAL FUNCTIONS
+// EXTERNAL VARIABLES
+// CONSTANTS
+// STATIC VARIABLE INITIALIZATIONS
+const UtlContainableType MpPortAudioStreamBase::TYPE
= "MpPortAudioStreamBase";
+
+// MACROS
+// GLOBAL VARIABLES
+// GLOBAL FUNCTIONS
+
+/* //////////////////////////// PUBLIC
//////////////////////////////////// */
+
+/* ============================ CREATORS
================================== */
+
+MpPortAudioStreamBase::MpPortAudioStreamBase(MpAudioStreamId streamId,
+ int outputChannelCount,
+ int inputChannelCount,
+ MpAudioDriverSampleFormat
outputSampleFormat,
+ MpAudioDriverSampleFormat
inputSampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer)
+: m_streamId(streamId)
+, m_outputChannelCount(outputChannelCount)
+, m_inputChannelCount(inputChannelCount)
+, m_outputSampleFormat(outputSampleFormat)
+, m_inputSampleFormat(inputSampleFormat)
+, m_sampleRate(sampleRate)
+, m_framesPerBuffer(framesPerBuffer)
+, m_inputSampleSize(0)
+, m_outputSampleSize(0)
+, m_inputVolumeMeter(NULL)
+, m_outputVolumeMeter(NULL)
+{
+ switch(m_inputSampleFormat & 0x3f)
+ {
+ case MP_AUDIO_FORMAT_FLOAT32:
+ m_inputSampleSize = sizeof(float);
+ m_inputVolumeMeter = NULL;
+ break;
+ case MP_AUDIO_FORMAT_INT32:
+ m_inputSampleSize = sizeof(int32_t);
+ m_inputVolumeMeter = new MpVolumeMeter<int32_t,
INT32_MAX>(inputChannelCount, sampleRate);
+ break;
+ case MP_AUDIO_FORMAT_INT24:
+ m_inputSampleSize = sizeof(char)*3;
+ m_inputVolumeMeter = NULL;
+ OsSysLog::add(FAC_AUDIO, PRI_WARNING, "Dangerous input sample format
selected, check MpPortAudioStreamBase.cpp\n");
+ break;
+ case MP_AUDIO_FORMAT_INT16:
+ m_inputSampleSize = sizeof(int16_t);
+ m_inputVolumeMeter = new MpVolumeMeter<int16_t,
INT16_MAX>(inputChannelCount, sampleRate);
+ break;
+ case MP_AUDIO_FORMAT_INT8:
+ m_inputSampleSize = sizeof(int8_t);
+ m_inputVolumeMeter = new MpVolumeMeter<int8_t,
INT8_MAX>(inputChannelCount, sampleRate);
+ break;
+ case MP_AUDIO_FORMAT_UINT8:
+ m_inputSampleSize = sizeof(uint8_t);
+ m_inputVolumeMeter = NULL;
+ break;
+ default:
+ // don't create buffers, unsupported sample format
+ break;
+ }
+
+ switch(m_outputSampleFormat & 0x3f)
+ {
+ case MP_AUDIO_FORMAT_FLOAT32:
+ m_outputSampleSize = sizeof(float);
+ m_outputVolumeMeter = NULL;
+ break;
+ case MP_AUDIO_FORMAT_INT32:
+ m_outputSampleSize = sizeof(int32_t);
+ m_outputVolumeMeter = new MpVolumeMeter<int32_t,
INT32_MAX>(outputChannelCount, sampleRate);
+ break;
+ case MP_AUDIO_FORMAT_INT24:
+ m_outputSampleSize = sizeof(char)*3;
+ m_outputVolumeMeter = NULL;
+ OsSysLog::add(FAC_AUDIO, PRI_WARNING, "Dangerous output sample
format selected, check MpPortAudioStreamBase.cpp\n");
+ break;
+ case MP_AUDIO_FORMAT_INT16:
+ m_outputSampleSize = sizeof(int16_t);
+ m_outputVolumeMeter = new MpVolumeMeter<int16_t,
INT16_MAX>(outputChannelCount, sampleRate);
+ break;
+ case MP_AUDIO_FORMAT_INT8:
+ m_outputSampleSize = sizeof(int8_t);
+ m_outputVolumeMeter = new MpVolumeMeter<int8_t,
INT8_MAX>(outputChannelCount, sampleRate);
+ break;
+ case MP_AUDIO_FORMAT_UINT8:
+ m_outputSampleSize = sizeof(uint8_t);
+ m_outputVolumeMeter = NULL;
+ break;
+ default:
+ // don't create buffers, unsupported sample format
+ break;
+ }
+
+ if (m_sampleRate < MIN_PORT_SAMPLE_RATE)
+ {
+ // we need a minimum due to division
+ m_sampleRate = MIN_PORT_SAMPLE_RATE;
+ }
+}
+
+MpPortAudioStreamBase::~MpPortAudioStreamBase()
+{
+ // delete volume meters if they exist
+ delete m_inputVolumeMeter;
+ m_inputVolumeMeter = NULL;
+ delete m_outputVolumeMeter;
+ m_outputVolumeMeter = NULL;
+}
+
+/* ============================ MANIPULATORS
============================== */
+
+void MpPortAudioStreamBase::resetStream()
+{
+ if (m_inputVolumeMeter)
+ {
+ m_inputVolumeMeter->resetMeter();
+ }
+
+ if (m_outputVolumeMeter)
+ {
+ m_outputVolumeMeter->resetMeter();
+ }
+}
+
+/* ============================ ACCESSORS
================================= */
+
+unsigned MpPortAudioStreamBase::hash() const
+{
+ return (unsigned)this;
+}
+
+UtlContainableType MpPortAudioStreamBase::getContainableType() const
+{
+ return MpPortAudioStreamBase::TYPE;
+}
+
+/* ============================ INQUIRY
=================================== */
+
+int MpPortAudioStreamBase::compareTo(UtlContainable const* inVal) const
+{
+ int result;
+
+ if (inVal->isInstanceOf(MpPortAudioStreamBase::TYPE))
+ {
+ result = hash() - inVal->hash();
+ }
+ else
+ {
+ result = -1;
+ }
+
+ return result;
+}
+
+double MpPortAudioStreamBase::getInputStreamVolume(MP_VOLUME_METER_TYPE
type) const
+{
+ if (m_inputVolumeMeter)
+ {
+ switch(type)
+ {
+ case MP_VOLUME_METER_VU:
+ return m_inputVolumeMeter->getVUVolume();
+ case MP_VOLUME_METER_PPM:
+ return m_inputVolumeMeter->getPPMVolume();
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+double MpPortAudioStreamBase::getOutputStreamVolume(MP_VOLUME_METER_TYPE
type) const
+{
+ if (m_outputVolumeMeter)
+ {
+ switch(type)
+ {
+ case MP_VOLUME_METER_VU:
+ return m_outputVolumeMeter->getVUVolume();
+ case MP_VOLUME_METER_PPM:
+ return m_outputVolumeMeter->getPPMVolume();
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/* //////////////////////////// PROTECTED
///////////////////////////////// */
+
+/* //////////////////////////// PRIVATE
/////////////////////////////////// */
+
+/* ============================ FUNCTIONS
================================= */
+
+
=======================================
--- /dev/null
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpSyncPortAudioStream.cpp
Sat Jan 15 07:00:40 2011
@@ -0,0 +1,110 @@
+//
+// Copyright (C) 2004-2006 SIPfoundry Inc.
+// Licensed by SIPfoundry under the LGPL license.
+//
+// Copyright (C) 2004-2006 Pingtel Corp. All rights reserved.
+// Licensed to SIPfoundry under a Contributor Agreement.
+//
+// Copyright (C) 2007 Jaroslav Libak
+// Licensed under the LGPL license.
+// $$
+///////////////////////////////////////////////////////////////////////////////
+
+// SYSTEM INCLUDES
+// APPLICATION INCLUDES
+#include <mp/MpSyncPortAudioStream.h>
+#include <mp/MpVolumeMeterBase.h>
+#include "portaudio.h"
+
+// DEFINES
+// EXTERNAL FUNCTIONS
+// EXTERNAL VARIABLES
+// CONSTANTS
+// STATIC VARIABLE INITIALIZATIONS
+// MACROS
+// GLOBAL VARIABLES
+// GLOBAL FUNCTIONS
+
+/* //////////////////////////// PUBLIC
//////////////////////////////////// */
+
+/* ============================ CREATORS
================================== */
+
+MpSyncPortAudioStream::MpSyncPortAudioStream(MpAudioStreamId streamId,
+ int outputChannelCount,
+ int inputChannelCount,
+ MpAudioDriverSampleFormat
outputSampleFormat,
+ MpAudioDriverSampleFormat
inputSampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer)
+: MpPortAudioStreamBase(streamId, outputChannelCount, inputChannelCount,
+ outputSampleFormat, inputSampleFormat,
+ sampleRate, framesPerBuffer)
+{
+
+}
+
+MpSyncPortAudioStream::~MpSyncPortAudioStream()
+{
+
+}
+
+/* ============================ MANIPULATORS
============================== */
+
+OsStatus MpSyncPortAudioStream::readStream(void *buffer, unsigned long
frames)
+{
+ OsStatus status = OS_FAILED;
+
+ PaError paError = Pa_ReadStream(m_streamId, buffer, frames);
+
+ if (paError == paNoError)
+ {
+ // copy input frames to meter
+ if (m_inputVolumeMeter)
+ {
+ m_inputVolumeMeter->pushBuffer(buffer, (unsigned int)frames);
+ }
+
+ status = OS_SUCCESS;
+ }
+ else if (paError == paInputOverflowed)
+ {
+ status = OS_OVERFLOW;
+ }
+
+ return status;
+}
+
+OsStatus MpSyncPortAudioStream::writeStream(const void *buffer, unsigned
long frames)
+{
+ OsStatus status = OS_FAILED;
+
+ // copy output frames to meter
+ if (m_outputVolumeMeter)
+ {
+ m_outputVolumeMeter->pushBuffer(buffer, (unsigned int)frames);
+ }
+
+ PaError paError = Pa_WriteStream(m_streamId, buffer, frames);
+
+ if (paError == paNoError)
+ {
+ status = OS_SUCCESS;
+ }
+ else if (paError == paOutputUnderflowed)
+ {
+ status = OS_OVERFLOW;
+ }
+
+ return status;
+}
+
+/* ============================ ACCESSORS
================================= */
+
+/* ============================ INQUIRY
=================================== */
+
+/* //////////////////////////// PROTECTED
///////////////////////////////// */
+
+/* //////////////////////////// PRIVATE
/////////////////////////////////// */
+
+/* ============================ FUNCTIONS
================================= */
+
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioStream.h
Wed Oct 22 12:27:37 2008
+++ /dev/null
@@ -1,202 +0,0 @@
-//
-// Copyright (C) 2007 Jaroslav Libak
-//
-// $$
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef MpPortAudioStream_h__
-#define MpPortAudioStream_h__
-
-// SYSTEM INCLUDES
-// APPLICATION INCLUDES
-#include <os/OsTime.h>
-#include <utl/UtlBool.h>
-#include "mp/MpAudioDriverDefs.h"
-#include "portaudio.h"
-
-// DEFINES
-// EXTERNAL FUNCTIONS
-// EXTERNAL VARIABLES
-// CONSTANTS
-// FORWARD DECLARATIONS
-class MpVolumeMeterBase;
-// STRUCTS
-// TYPEDEFS
-// MACROS
-// GLOBAL VARIABLES
-// GLOBAL FUNCTIONS
-
-/**
-* Representation of asynchronous portlib audio stream. For synchronous
streams, it is not
-* needed. Stream can be output/input/full duplex. It is only used for
callback. Callback
-* and main thread share the same buffer using lockless algorithm. The
basis of the algorithm
-* is that each thread writes to its own volatile variable, and reads from
other threads variable.
-* No 2 threads write to the same variable. When writing to buffer, writing
pointer can never
-* exceed or equal reading pointer, and when reading, reading pointer
cannot exceed or equal
-* to writing pointer. Thus threads will always use disjoint memory blocks.
-* Statistics about input/output underflows and overflows are computed and
can be printed if needed.
-*/
-class MpPortAudioStream
-{
- /* //////////////////////////// PUBLIC
//////////////////////////////////// */
-public:
- /* ============================ CREATORS
================================== */
- ///@name Creators
- //@{
-
- /// Constructor.
- MpPortAudioStream(int outputChannelCount,
- int inputChannelCount,
- MpAudioDriverSampleFormat outputSampleFormat,
- MpAudioDriverSampleFormat inputSampleFormat,
- double sampleRate,
- unsigned long framesPerBuffer);
-
- /// Destructor.
- ~MpPortAudioStream(void);
- //@}
-
- /* ============================ MANIPULATORS
============================== */
- ///@name Manipulators
- //@{
-
- /**
- * audio callback according to portaudio spec. In user data it receives
- * pointer to MpPortAudioStream instance
- */
- static int streamCallback(const void *input,
- void *output,
- unsigned long frameCount,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData );
-
- /**
- * Reads given number of frames into buffer. Buffer must be allocated
memory.
- *
- * @param buffer Allocated memory to read data into
- * @param frames Number of frames to read
- * @returns OS_SUCCESS if successful
- */
- OsStatus readStreamAsync(void *buffer,
- unsigned long frames);
-
- /**
- * Writes given number of frames into stream from buffer.
- *
- * @param buffer Buffer with samples
- * @param frames Number of frames to write to stream
- * @returns OS_SUCCESS if successful
- */
- OsStatus writeStreamAsync(const void *buffer,
- unsigned long frames);
-
- /**
- * Gets volume for input stream calculated from samples.
- */
- double getInputStreamVolume(MP_VOLUME_METER_TYPE type) const;
-
- /**
- * Gets volume for output stream calculated from samples.
- */
- double getOutputStreamVolume(MP_VOLUME_METER_TYPE type) const;
-
- /**
- * Prints overflow/underflow statistics.
- */
- void printStatistics();
-
- /**
- * Resets internal stream buffers to 0 and resets statistics. Needs to
be done
- * after stream is stopped or aborted. Not thread safe.
- */
- void resetStream();
-
- //@}
-
- /* ============================ ACCESSORS
================================= */
- ///@name Accessors
- //@{
- //@}
- /* ============================ INQUIRY
=================================== */
- ///@name Inquiry
- //@{
- //@}
-
- /* //////////////////////////// PROTECTED
///////////////////////////////// */
-protected:
-
- /* //////////////////////////// PRIVATE
/////////////////////////////////// */
-private:
-
- /// Copy constructor (not implemented for this class)
- MpPortAudioStream(const MpPortAudioStream& rMpPortAudioStream);
-
- /// Assignment operator (not implemented for this class)
- MpPortAudioStream& operator=(const MpPortAudioStream& rhs);
-
- /**
- * Stream callback of this instance to support multiple streams.
- */
- int instanceStreamCallback(const void *input,
- void *output,
- unsigned long frameCount,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags);
-
- /**
- * Gets maximum bytes that can be copied from input to output pos
without exceeding it.
- * It is useful when preventing inputPos exceeding outputPos.
- */
- int getCopyableBytes(unsigned int inputPos, unsigned int outputPos,
unsigned int maxPos) const;
-
- /**
- * Gets actual number of frames in input buffer
- */
- int getInputBufferFrameCount();
-
- /**
- * Gets actual number of frames in output buffer
- */
- int getOutputBufferFrameCount();
-
- int m_outputChannelCount; ///< number of output channels
- int m_inputChannelCount; ///< number of input channels
- MpAudioDriverSampleFormat m_outputSampleFormat; ///< sample format of
output
- MpAudioDriverSampleFormat m_inputSampleFormat; ///< sample format of
input
- double m_sampleRate; ///< sample rate for stream
- unsigned long m_framesPerBuffer; ///< frames per buffer for stream
- unsigned long m_virtualFramesPerBuffer; ///< only used for initializing
m_inputWritePos and m_outputWritePos
-
- void* m_pInputBuffer; ///< buffer for storing recorded samples
- void* m_pOutputBuffer; ///< buffer for storing frames going to speaker
- unsigned int m_inputBufferSize; ///< size of input buffer
- unsigned int m_outputBufferSize; ///< size of output buffer
- unsigned int m_inputSampleSize; ///< size of input sample in bytes per
channel
- unsigned int m_outputSampleSize; ///< size of output sample in bytes
per channel
- volatile unsigned int m_inputWritePos; ///< position in input buffer
for writing
- volatile unsigned int m_inputReadPos; ///< position in input buffer for
reading
- volatile unsigned int m_outputWritePos; ///< position in output buffer
for writing
- volatile unsigned int m_outputReadPos; ///< position in output buffer
for reading
-
- MpVolumeMeterBase* m_inputVolumeMeter; ///< volume meter for input
- MpVolumeMeterBase* m_outputVolumeMeter; ///< volume meter for output
-
- unsigned int m_outputBufferOverflow;
- unsigned int m_outputBufferUnderflow;
- unsigned int m_inputBufferOverflow;
- unsigned int m_inputBufferUnderflow;
-
- volatile bool m_inputBufferPrefetchMode; ///< whether input buffer is
in prefetch mode
- volatile bool m_outputBufferPrefetchMode; ///< whether output buffer is
in prefetch mode
- unsigned int m_inputPrefetchCount; ///< input buffer latency in frames
- unsigned int m_outputPrefetchCount; ///< output buffer latency in frames
-
- bool m_bFrameRecorded; ///< whether at least one frame has been recorded
- bool m_bFramePushed; ///< whether at least one frame has been pushed
-
- int m_streamReadWriteCount;
- int m_callbackCallCount;
-};
-
-#endif // MpPortAudioStream_h__
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioStream.cpp Wed
Oct 22 11:32:45 2008
+++ /dev/null
@@ -1,678 +0,0 @@
-//
-// Copyright (C) 2007 Jaroslav Libak
-// Licensed under the LGPL license.
-// $$
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef DISABLE_LOCAL_AUDIO
-
-// SYSTEM INCLUDES
-// APPLICATION INCLUDES
-#include <assert.h>
-#include <os/OsIntTypes.h>
-#include <os/OsSysLog.h>
-#include <os/OsDateTime.h>
-#include "mp/MpPortAudioStream.h"
-#include "mp/MpVolumeMeter.h"
-
-
-// DEFINES
-#define MIN_SAMPLE_RATE 200
-//#define DEBUG_AUDIO_STREAM
-#define INPUT_PREFETCH_BUFFERS_COUNT 8
-#define OUTPUT_PREFETCH_BUFFERS_COUNT 8
-
-// EXTERNAL FUNCTIONS
-// EXTERNAL VARIABLES
-// CONSTANTS
-// STATIC VARIABLE INITIALIZATIONS
-// MACROS
-// GLOBAL VARIABLES
-// GLOBAL FUNCTIONS
-
-/* //////////////////////////// PUBLIC
//////////////////////////////////// */
-
-/* ============================ CREATORS
================================== */
-
-MpPortAudioStream::MpPortAudioStream(int outputChannelCount,
- int inputChannelCount,
- MpAudioDriverSampleFormat
outputSampleFormat,
- MpAudioDriverSampleFormat
inputSampleFormat,
- double sampleRate,
- unsigned long framesPerBuffer)
-: m_outputChannelCount(outputChannelCount)
-, m_inputChannelCount(inputChannelCount)
-, m_outputSampleFormat(outputSampleFormat)
-, m_inputSampleFormat(inputSampleFormat)
-, m_sampleRate(sampleRate)
-, m_framesPerBuffer(framesPerBuffer)
-, m_virtualFramesPerBuffer(0)
-, m_pInputBuffer(NULL)
-, m_pOutputBuffer(NULL)
-, m_inputBufferSize(0)
-, m_outputBufferSize(0)
-, m_inputSampleSize(0)
-, m_outputSampleSize(0)
-, m_inputWritePos(0)
-, m_inputReadPos(0)
-, m_outputWritePos(0)
-, m_outputReadPos(0)
-, m_outputBufferOverflow(0)
-, m_outputBufferUnderflow(0)
-, m_inputBufferOverflow(0)
-, m_inputBufferUnderflow(0)
-, m_inputBufferPrefetchMode(true)
-, m_outputBufferPrefetchMode(true)
-, m_inputPrefetchCount(0)
-, m_outputPrefetchCount(0)
-, m_bFrameRecorded(false)
-, m_bFramePushed(false)
-, m_streamReadWriteCount(0)
-, m_callbackCallCount(0)
-, m_inputVolumeMeter(NULL)
-, m_outputVolumeMeter(NULL)
-{
- switch(m_inputSampleFormat & 0x3f)
- {
- case MP_AUDIO_FORMAT_FLOAT32:
- m_inputSampleSize = sizeof(float);
- m_inputVolumeMeter = NULL;
- break;
- case MP_AUDIO_FORMAT_INT32:
- m_inputSampleSize = sizeof(int32_t);
- m_inputVolumeMeter = new MpVolumeMeter<int32_t,
INT32_MAX>(inputChannelCount, sampleRate);
- break;
- case MP_AUDIO_FORMAT_INT24:
- m_inputSampleSize = sizeof(char)*3;
- m_inputVolumeMeter = NULL;
- OsSysLog::add(FAC_AUDIO, PRI_WARNING, "Dangerous input sample format
selected, check MpPortAudioStream.cpp\n");
- break;
- case MP_AUDIO_FORMAT_INT16:
- m_inputSampleSize = sizeof(int16_t);
- m_inputVolumeMeter = new MpVolumeMeter<int16_t,
INT16_MAX>(inputChannelCount, sampleRate);
- break;
- case MP_AUDIO_FORMAT_INT8:
- m_inputSampleSize = sizeof(int8_t);
- m_inputVolumeMeter = new MpVolumeMeter<int8_t,
INT8_MAX>(inputChannelCount, sampleRate);
- break;
- case MP_AUDIO_FORMAT_UINT8:
- m_inputSampleSize = sizeof(uint8_t);
- m_inputVolumeMeter = NULL;
- break;
- default:
- // don't create buffers, unsupported sample format
- break;
- }
-
- switch(m_outputSampleFormat & 0x3f)
- {
- case MP_AUDIO_FORMAT_FLOAT32:
- m_outputSampleSize = sizeof(float);
- m_outputVolumeMeter = NULL;
- break;
- case MP_AUDIO_FORMAT_INT32:
- m_outputSampleSize = sizeof(int32_t);
- m_outputVolumeMeter = new MpVolumeMeter<int32_t,
INT32_MAX>(outputChannelCount, sampleRate);
- break;
- case MP_AUDIO_FORMAT_INT24:
- m_outputSampleSize = sizeof(char)*3;
- m_outputVolumeMeter = NULL;
- OsSysLog::add(FAC_AUDIO, PRI_WARNING, "Dangerous output sample
format selected, check MpPortAudioStream.cpp\n");
- break;
- case MP_AUDIO_FORMAT_INT16:
- m_outputSampleSize = sizeof(int16_t);
- m_outputVolumeMeter = new MpVolumeMeter<int16_t,
INT16_MAX>(outputChannelCount, sampleRate);
- break;
- case MP_AUDIO_FORMAT_INT8:
- m_outputSampleSize = sizeof(int8_t);
- m_outputVolumeMeter = new MpVolumeMeter<int8_t,
INT8_MAX>(outputChannelCount, sampleRate);
- break;
- case MP_AUDIO_FORMAT_UINT8:
- m_outputSampleSize = sizeof(uint8_t);
- m_outputVolumeMeter = NULL;
- break;
- default:
- // don't create buffers, unsupported sample format
- break;
- }
-
- if (m_sampleRate < MIN_SAMPLE_RATE)
- {
- // we need a minimum due to division
- m_sampleRate = MIN_SAMPLE_RATE;
- }
-
- m_virtualFramesPerBuffer = m_framesPerBuffer;
-
- if (m_virtualFramesPerBuffer == 0)
- {
- // callback will accept frames of any size anyway...
- // use 160 for now, we need to create buffers of certain size, but
will accept any number of frames
- m_virtualFramesPerBuffer = 160;
- }
-
- // allocate input buffer
- if (m_inputSampleFormat > 0 && m_inputChannelCount > 0)
- {
- unsigned int inputFrameSize = m_inputSampleSize *
m_inputChannelCount;
- unsigned int inputBufferReserve = ((unsigned int)m_sampleRate /
MIN_SAMPLE_RATE + 5);
- m_inputBufferSize = inputFrameSize * m_virtualFramesPerBuffer *
inputBufferReserve;
- m_inputPrefetchCount = min(INPUT_PREFETCH_BUFFERS_COUNT,
inputBufferReserve) * m_virtualFramesPerBuffer;
- m_pInputBuffer = malloc(m_inputBufferSize);
-
- if (!m_pInputBuffer)
- {
- // allocation error, don't use buffer
- m_inputBufferSize = 0;
- }
- else
- {
- // zero buffer
- memset(m_pInputBuffer, 0, m_inputBufferSize);
- // start writing at the next sample position
- m_inputWritePos = inputFrameSize;
- }
- }
-
- // allocate output buffer
- if (m_outputSampleSize > 0 && m_outputChannelCount > 0)
- {
- unsigned int outputFrameSize = m_outputSampleSize *
m_outputChannelCount;
- unsigned int outputBufferReserve = ((unsigned int)m_sampleRate /
MIN_SAMPLE_RATE + 5);
- m_outputBufferSize = outputFrameSize * m_virtualFramesPerBuffer *
outputBufferReserve;
- m_outputPrefetchCount = min(OUTPUT_PREFETCH_BUFFERS_COUNT,
outputBufferReserve) * m_virtualFramesPerBuffer;
- m_pOutputBuffer = malloc(m_outputBufferSize);
-
- if (!m_pOutputBuffer)
- {
- // allocation error, don't use buffer
- m_outputBufferSize = 0;
- }
- else
- {
- // zero buffer
- memset(m_pOutputBuffer, 0, m_outputBufferSize);
- // start writing at the next sample position
- m_outputWritePos = outputFrameSize;
- }
- }
-}
-
-MpPortAudioStream::~MpPortAudioStream(void)
-{
- if (m_pInputBuffer)
- {
- free(m_pInputBuffer);
- m_pInputBuffer = NULL;
- }
-
- if (m_pOutputBuffer)
- {
- free(m_pOutputBuffer);
- m_pOutputBuffer = NULL;
- }
-
- // delete volume meters if they exist
- delete m_inputVolumeMeter;
- m_inputVolumeMeter = NULL;
- delete m_outputVolumeMeter;
- m_outputVolumeMeter = NULL;
-}
-
-/* ============================ MANIPULATORS
============================== */
-
-int MpPortAudioStream::streamCallback(const void *input,
- void *output,
- unsigned long frameCount,
- const PaStreamCallbackTimeInfo*
timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData)
-{
- if (userData)
- {
- MpPortAudioStream* instance = (MpPortAudioStream*)userData;
-
- return instance->instanceStreamCallback(input, output, frameCount,
timeInfo, statusFlags);
- }
-
- return paContinue;
-}
-
-OsStatus MpPortAudioStream::readStreamAsync(void *buffer,
- unsigned long frames)
-{
- OsStatus status = OS_FAILED;
-
-#ifdef DEBUG_AUDIO_STREAM
- if (m_bFrameRecorded && m_streamReadWriteCount++ % 200 == 0)
- {
- this->printStatistics();
- }
-#endif
-
- if (frames > 0 && m_inputSampleSize > 0)
- {
- if ((m_framesPerBuffer == 0) || (m_framesPerBuffer == frames))
- {
- // count number of required bytes in buffer
- unsigned int bytesRequired = m_inputSampleSize *
m_inputChannelCount * frames;
-
- if (m_inputBufferPrefetchMode)
- {
- // input is in prefetch mode, send zeroes only
- memset(buffer, 0, bytesRequired);
- status = OS_PREFETCH;
- return status;
- }
-
- unsigned int copyable = getCopyableBytes(m_inputReadPos,
m_inputWritePos, m_inputBufferSize);
- unsigned int bytesToCopy = min(bytesRequired, copyable);
- unsigned int framesToCopy = bytesToCopy / (m_inputSampleSize *
m_inputChannelCount);
-
- if (framesToCopy < frames)
- {
- // we are out of buffer
- if (m_bFrameRecorded)
- {
- // record underflows only since the 1st frame was recorded
- m_inputBufferUnderflow++;
- }
- status = OS_UNDERFLOW;
- }
- else if (framesToCopy == frames)
- {
- status = OS_SUCCESS;
- }
-
- if (framesToCopy > 0)
- {
- unsigned int realBytesToCopy = framesToCopy *
m_inputSampleSize * m_inputChannelCount;
-
- // count1 is number of bytes to copy before wrapping occurs
- int count1 = min(realBytesToCopy, m_inputBufferSize -
m_inputReadPos);
- // count 2 is number of bytes to copy after wrapping
- int count2 = realBytesToCopy - count1;
- // now copy some frames
- memcpy(buffer, (char*)m_pInputBuffer + m_inputReadPos, count1);
- if (count2 > 0)
- {
- // handle wrap around
- memcpy((char*)buffer + count1, m_pInputBuffer, count2);
- }
- m_inputReadPos = (m_inputReadPos + realBytesToCopy) %
m_inputBufferSize;
- }
- }
- }
-
- return status;
-}
-
-OsStatus MpPortAudioStream::writeStreamAsync(const void *buffer,
- unsigned long frames)
-{
- OsStatus status = OS_FAILED;
-
-#ifdef DEBUG_AUDIO_STREAM
- if (m_bFramePushed && m_streamReadWriteCount++ % 200 == 0)
- {
- this->printStatistics();
- }
-#endif
-
- if (frames > 0 && m_outputSampleSize > 0)
- {
- if ((m_framesPerBuffer == 0) || (m_framesPerBuffer == frames))
- {
- // count number of required bytes in buffer
- unsigned int bytesRequired = m_outputSampleSize *
m_outputChannelCount * frames;
-
- unsigned int copyable = getCopyableBytes(m_outputWritePos,
m_outputReadPos, m_outputBufferSize);
- unsigned int bytesToCopy = min(bytesRequired, copyable);
- unsigned int framesToCopy = bytesToCopy / (m_outputSampleSize *
m_outputChannelCount);
-
- if (framesToCopy < frames)
- {
- // we are out of buffer
- OsSysLog::add(FAC_AUDIO, PRI_WARNING, "Output stream buffer
overflow!\n");
- m_outputBufferOverflow++;
- status = OS_OVERFLOW;
- }
- else if (framesToCopy == frames)
- {
- status = OS_SUCCESS;
- }
-
- if (framesToCopy > 0)
- {
- m_bFramePushed = true;
- unsigned int realBytesToCopy = framesToCopy *
m_outputSampleSize * m_outputChannelCount;
-
- // count1 is number of bytes to copy before wrapping occurs
- int count1 = min(realBytesToCopy, m_outputBufferSize -
m_outputWritePos);
- // count 2 is number of bytes to copy after wrapping
- int count2 = realBytesToCopy - count1;
- // now copy some frames
- memcpy((char*)m_pOutputBuffer + m_outputWritePos, buffer,
count1);
- if (count2 > 0)
- {
- // handle wrap around
- memcpy(m_pOutputBuffer, (char*)buffer + count1, count2);
- }
- m_outputWritePos = (m_outputWritePos + realBytesToCopy) %
m_outputBufferSize;
- }
- }
- }
-
- return status;
-}
-
-double MpPortAudioStream::getInputStreamVolume(MP_VOLUME_METER_TYPE type)
const
-{
- if (m_inputVolumeMeter)
- {
- switch(type)
- {
- case MP_VOLUME_METER_VU:
- return m_inputVolumeMeter->getVUVolume();
- case MP_VOLUME_METER_PPM:
- return m_inputVolumeMeter->getPPMVolume();
- default:
- return 0;
- }
- }
-
- return 0;
-}
-
-double MpPortAudioStream::getOutputStreamVolume(MP_VOLUME_METER_TYPE type)
const
-{
- if (m_outputVolumeMeter)
- {
- switch(type)
- {
- case MP_VOLUME_METER_VU:
- return m_outputVolumeMeter->getVUVolume();
- case MP_VOLUME_METER_PPM:
- return m_outputVolumeMeter->getPPMVolume();
- default:
- return 0;
- }
- }
-
- return 0;
-}
-
-void MpPortAudioStream::printStatistics()
-{
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"---------
MpPortAudioStream::printStatistics ---------\n");
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_outputBufferOverflow = %d\n",
m_outputBufferOverflow);
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_outputBufferUnderflow = %d\n",
m_outputBufferUnderflow);
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_inputBufferOverflow = %d\n",
m_inputBufferOverflow);
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_inputBufferUnderflow = %d\n",
m_inputBufferUnderflow);
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_streamReadWriteCount = %d\n",
m_streamReadWriteCount);
- OsSysLog::add(FAC_AUDIO, PRI_DEBUG,"m_callbackCallCount = %d\n",
m_callbackCallCount);
- OsSysLog::add(FAC_AUDIO,
PRI_DEBUG,"------------------------------------------------------\n");
-}
-
-void MpPortAudioStream::resetStream()
-{
- m_inputWritePos = 0;
- m_inputReadPos = 0;
- m_outputWritePos = 0;
- m_outputReadPos = 0;
-
- // zero buffers
- if (m_pInputBuffer)
- {
- memset(m_pInputBuffer, 0, m_inputBufferSize);
- m_inputWritePos = m_inputSampleSize * m_inputChannelCount;
- }
-
- if (m_pOutputBuffer)
- {
- memset(m_pOutputBuffer, 0, m_outputBufferSize);
- m_outputWritePos = m_outputSampleSize * m_outputChannelCount;
- }
-
- // reset statistics
- m_outputBufferOverflow = 0;
- m_outputBufferUnderflow = 0;
- m_inputBufferOverflow = 0;
- m_inputBufferUnderflow = 0;
- m_bFrameRecorded = false;
- m_bFramePushed = false;
- m_inputBufferPrefetchMode = true;
- m_outputBufferPrefetchMode = true;
-
- if (m_inputVolumeMeter)
- {
- m_inputVolumeMeter->resetMeter();
- }
-
- if (m_outputVolumeMeter)
- {
- m_outputVolumeMeter->resetMeter();
- }
-}
-
-/* ============================ ACCESSORS
================================= */
-
-/* ============================ INQUIRY
=================================== */
-
-/* //////////////////////////// PROTECTED
///////////////////////////////// */
-
-/* //////////////////////////// PRIVATE
/////////////////////////////////// */
-
-int MpPortAudioStream::instanceStreamCallback(const void *input,
- void *output,
- unsigned long frameCount,
- const
PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags
statusFlags)
-{
- // portaudio supplied us pointers to its input and output buffers
-
-#ifdef DEBUG_AUDIO_STREAM
- if (m_bFrameRecorded || m_bFramePushed)
- {
- m_callbackCallCount++;
- }
-#endif
-
- if (frameCount > 0)
- {
- // handle output frames
- if (m_outputChannelCount > 0 && output && m_outputSampleSize > 0)
- {
- // copy output frames to meter
- if (m_outputVolumeMeter)
- {
- m_outputVolumeMeter->pushBuffer(output, frameCount);
- }
-
- unsigned int outputFrameCount = getOutputBufferFrameCount();
-
- if (m_outputBufferPrefetchMode)
- {
- // prefetch is on
- if (outputFrameCount > m_outputPrefetchCount)
- {
- // we have enough frames, disable prefetch mode
- m_outputBufferPrefetchMode = false;
- }
- }
- else
- {
- // prefetch is off
- if (outputFrameCount <= 0)
- {
- // we are out of buffer
- if (m_bFramePushed)
- {
- // record only underflows since the first push
- m_outputBufferUnderflow++;
- }
- // buffer is empty, enable prefetch
- m_outputBufferPrefetchMode = true;
- }
- }
-
- // count number of required bytes in buffer
- unsigned int bytesRequired = m_outputSampleSize *
m_outputChannelCount * frameCount;
-
- unsigned int copyable = 0;
- if (!m_outputBufferPrefetchMode)
- {
- copyable = getCopyableBytes(m_outputReadPos, m_outputWritePos,
m_outputBufferSize);
- }
- unsigned int bytesToCopy = min(bytesRequired, copyable);
- unsigned int framesToCopy = bytesToCopy / (m_outputSampleSize *
m_outputChannelCount);
- unsigned int zeroFrames = 0;
-
- if (framesToCopy < frameCount && !m_outputBufferPrefetchMode)
- {
- // we will have to copy zeroFrames filled with 0s, as we don't
have enough data
- zeroFrames = frameCount - framesToCopy;
- }
-
- if (framesToCopy > 0)
- {
- unsigned int realBytesToCopy = framesToCopy *
m_outputSampleSize * m_outputChannelCount;
-
- // count1 is number of bytes to copy before wrapping occurs
- int count1 = min(realBytesToCopy, m_outputBufferSize -
m_outputReadPos);
- // count 2 is number of bytes to copy after wrapping
- int count2 = realBytesToCopy - count1;
- // now copy some frames
- memcpy(output, (char*)m_pOutputBuffer + m_outputReadPos,
count1);
- if (count2 > 0)
- {
- // handle wrap around
- memcpy((char*)output + count1, m_pOutputBuffer, count2);
- }
-
- // fill zeroFrames with 0s
- if (zeroFrames > 0)
- {
- char* outputBuff = (char*)output + count1 + count2;
- unsigned int zeroBytesToCopy = zeroFrames *
m_outputSampleSize * m_outputChannelCount;
- for (unsigned int i = 0; i < zeroBytesToCopy; i++)
- {
- *outputBuff++ = 0;
- }
- }
-
- m_outputReadPos = (m_outputReadPos + realBytesToCopy) %
m_outputBufferSize;
- }
- else
- {
- // prefetch is on, or buffer is empty
- // output zeros
- memset(output, 0, bytesRequired);
- }
- }
-
- // handle input frames
- if (m_inputChannelCount > 0 && input && m_inputSampleSize > 0)
- {
- // copy input frames to meter
- if (m_inputVolumeMeter)
- {
- m_inputVolumeMeter->pushBuffer(input, frameCount);
- }
-
- unsigned int inputFrameCount = getInputBufferFrameCount();
-
- if (m_inputBufferPrefetchMode)
- {
- // prefetch is on
- if (inputFrameCount > m_inputPrefetchCount)
- {
- // we have enough frames, disable prefetch mode
- m_inputBufferPrefetchMode = false;
- }
- }
- else
- {
- // prefetch is off
- if (inputFrameCount <= 0)
- {
- // buffer is empty, enable prefetch
- m_inputBufferPrefetchMode = true;
- }
- }
-
- // count number of required bytes in buffer
- unsigned int bytesRequired = m_inputSampleSize *
m_inputChannelCount * frameCount;
-
- unsigned int copyable = getCopyableBytes(m_inputWritePos,
m_inputReadPos, m_inputBufferSize);
- unsigned int bytesToCopy = min(bytesRequired, copyable);
- unsigned int framesToCopy = bytesToCopy / (m_inputSampleSize *
m_inputChannelCount);
-
- if (framesToCopy < frameCount)
- {
- // we are out of buffer
- m_inputBufferOverflow++;
- }
-
- if (framesToCopy > 0)
- {
- m_bFrameRecorded = true;
- unsigned int realBytesToCopy = framesToCopy *
m_inputSampleSize * m_inputChannelCount;
-
- // count1 is number of bytes to copy before wrapping occurs
- int count1 = min(realBytesToCopy, m_inputBufferSize -
m_inputWritePos);
- // count 2 is number of bytes to copy after wrapping
- int count2 = realBytesToCopy - count1;
- // now copy some frames
- memcpy((char*)m_pInputBuffer + m_inputWritePos, input, count1);
- if (count2 > 0)
- {
- // handle wrap around
- memcpy(m_pInputBuffer, (char*)input + count1, count2);
- }
-
- // advance m_inputWritePos by realBytesToCopy
- m_inputWritePos = (m_inputWritePos + realBytesToCopy) %
m_inputBufferSize;
- }
- }
- }
-
- return paContinue;
-}
-
-int MpPortAudioStream::getCopyableBytes(unsigned int inputPos,
- unsigned int outputPos,
- unsigned int maxPos) const
-{
- if (inputPos < outputPos)
- {
- if (inputPos < maxPos && outputPos < maxPos)
- {
- return outputPos - inputPos - 1;
- }
- }
- else if (inputPos > outputPos)
- {
- if (outputPos < maxPos)
- {
- return maxPos - inputPos + outputPos - 1;
- }
- }
-
- return 0;
-}
-
-int MpPortAudioStream::getInputBufferFrameCount()
-{
- return getCopyableBytes(m_inputReadPos, m_inputWritePos,
m_inputBufferSize) / (m_inputSampleSize * m_inputChannelCount);
-}
-
-int MpPortAudioStream::getOutputBufferFrameCount()
-{
- return getCopyableBytes(m_outputReadPos, m_outputWritePos,
m_outputBufferSize) / (m_outputSampleSize * m_outputChannelCount);
-}
-
-/* ============================ FUNCTIONS
================================= */
-
-
-#endif // DISABLE_LOCAL_AUDIO
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/include/Makefile.am Wed Dec 30
01:54:39 2009
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/include/Makefile.am Sat Jan 15
07:00:40 2011
@@ -13,6 +13,7 @@
mp/HandsetFilterBank.h \
mp/HandsetFilterbankWindows.h \
mp/MpArrayBuf.h \
+ mp/MpAsyncPortAudioStream.h \
mp/MpAudioAbstract.h \
mp/MpAudioBuf.h \
mp/MpAudioDeviceInfo.h \
@@ -67,7 +68,7 @@
mp/MpPlayerListener.h \
mp/MpPortAudioDriver.h \
mp/MpPortAudioMixer.h \
- mp/MpPortAudioStream.h \
+ mp/MpPortAudioStreamBase.h \
mp/MpQueuePlayerListener.h \
mp/MpRawAudioBuffer.h \
mp/MpResNotification.h \
@@ -89,6 +90,7 @@
mp/MpStreamPlayer.h \
mp/MpStreamPlaylistPlayer.h \
mp/MpStreamQueuePlayer.h \
+ mp/MpSyncPortAudioStream.h \
mp/MpToneResourceMsg.h \
mp/MpTopologyGraph.h \
mp/MpTypes.h \
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpAudioDriverBase.h
Wed Oct 22 12:27:37 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpAudioDriverBase.h
Sat Jan 15 07:00:40 2011
@@ -295,7 +295,8 @@
virtual OsStatus getStreamCpuLoad(MpAudioStreamId stream, double&
cpuLoad) const = 0;

/**
- * Read from a given synchronous stream given number of frames.
+ * Read from a given stream given number of frames. Stream may be
synchronous or
+ * asynchronous.
*
* @param stream Id of audio stream
* @param buffer Buffer to read into. Note that different sample sizes
can be set
@@ -305,44 +306,13 @@
* @returns OS_SUCCESS if successful, OS_OVERFLOW if successful but some
data
* was lost before
*/
- virtual OsStatus readStreamSync(MpAudioStreamId stream,
- void *buffer,
- unsigned long frames) = 0;
+ virtual OsStatus readStream(MpAudioStreamId stream,
+ void *buffer,
+ unsigned long frames) = 0;

/**
- * Write into a given synchronous stream given number of frames.
- *
- * @param stream Id of audio stream
- * @param buffer Buffer to write from. Note that different sample sizes
can be set
- * on stream.
- * @param frames Number of frames to written from buffer. The actual
number of bytes
- * copied depends on sample size.
- * @returns OS_SUCCESS if successful, OS_UNDERFLOW if successful but
some data
- * had to be inserted before
- */
- virtual OsStatus writeStreamSync(MpAudioStreamId stream,
- const void *buffer,
- unsigned long frames) = 0;
-
- /**
- * Read from a given asynchronous stream given number of frames. Cannot
be used
- * with synchronous streams.
- *
- * @param stream Id of audio stream
- * @param buffer Buffer to read into. Note that different sample sizes
can be set
- * on stream.
- * @param frames Number of frames to read into buffer. The actual number
of bytes
- * copied depends on sample size.
- * @returns OS_SUCCESS if successful, OS_OVERFLOW if successful but some
data
- * was lost before
- */
- virtual OsStatus readStreamAsync(MpAudioStreamId stream,
- void *buffer,
- unsigned long frames) = 0;
-
- /**
- * Write into a given asynchronous stream given number of frames. Cannot
be used
- * with synchronous streams.
+ * Write into a given stream given number of frames. Stream may be
synchronous or
+ * asynchronous.
*
* @param stream Id of audio stream
* @param buffer Buffer to write from. Note that different sample sizes
can be set
@@ -351,9 +321,9 @@
* copied depends on sample size.
* @returns OS_SUCCESS if successful
*/
- virtual OsStatus writeStreamAsync(MpAudioStreamId stream,
- const void *buffer,
- unsigned long frames) = 0;
+ virtual OsStatus writeStream(MpAudioStreamId stream,
+ const void *buffer,
+ unsigned long frames) = 0;

/**
* Gets number of frames that can be read from a synchronous audio
stream without
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioDriver.h
Wed Oct 22 12:27:37 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/include/mp/MpPortAudioDriver.h
Sat Jan 15 07:00:40 2011
@@ -268,42 +268,8 @@
virtual OsStatus getStreamCpuLoad(MpAudioStreamId stream, double&
cpuLoad) const;

/**
- * Read from a given synchronous stream given number of frames. Only 1
thread
- * can call this function at time, as thread safety of portaudio streams
- * is uncertain.
- *
- * @param stream Id of audio stream
- * @param buffer Buffer to read into. Note that different sample sizes
can be set
- * on stream.
- * @param frames Number of frames to read into buffer. The actual
number of bytes
- * copied depends on sample size.
- * @returns OS_SUCCESS if successful, OS_OVERFLOW if successful but
some data
- * was lost before
- */
- virtual OsStatus readStreamSync(MpAudioStreamId stream,
- void *buffer,
- unsigned long frames);
-
- /**
- * Write into a given synchronous stream given number of frames. Only 1
thread
- * can call this function at time, as thread safety of portaudio streams
- * is uncertain.
- *
- * @param stream Id of audio stream
- * @param buffer Buffer to write from. Note that different sample sizes
can be set
- * on stream.
- * @param frames Number of frames to written from buffer. The actual
number of bytes
- * copied depends on sample size.
- * @returns OS_SUCCESS if successful, OS_UNDERFLOW if successful but
some data
- * had to be inserted before
- */
- virtual OsStatus writeStreamSync(MpAudioStreamId stream,
- const void *buffer,
- unsigned long frames);
-
- /**
- * Read from a given asynchronous stream given number of frames. Cannot
be used
- * with synchronous streams.
+ * Read from a given stream given number of frames. Stream may be
synchronous or
+ * asynchronous.
*
* @param stream Id of audio stream
* @param buffer Buffer to read into. Note that different sample sizes
can be set
@@ -313,13 +279,13 @@
* @returns OS_SUCCESS if successful, OS_OVERFLOW if successful but some
data
* was lost before
*/
- virtual OsStatus readStreamAsync(MpAudioStreamId stream,
- void *buffer,
- unsigned long frames);
+ virtual OsStatus readStream(MpAudioStreamId stream,
+ void *buffer,
+ unsigned long frames);

/**
- * Write into a given asynchronous stream given number of frames. Cannot
be used
- * with synchronous streams.
+ * Write into a given stream given number of frames. Stream may be
synchronous or
+ * asynchronous.
*
* @param stream Id of audio stream
* @param buffer Buffer to write from. Note that different sample sizes
can be set
@@ -328,9 +294,9 @@
* copied depends on sample size.
* @returns OS_SUCCESS if successful
*/
- virtual OsStatus writeStreamAsync(MpAudioStreamId stream,
- const void *buffer,
- unsigned long frames);
+ virtual OsStatus writeStream(MpAudioStreamId stream,
+ const void *buffer,
+ unsigned long frames);


/**
@@ -462,7 +428,7 @@
/**
* Resets stream if its asynchronous.
*/
- void resetAsyncStream(MpAudioStreamId stream);
+ void resetStreamInternal(MpAudioStreamId stream);

/**
* Checks whether this stream exists.
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/sipXmediaLib-msvc71.vcproj Wed
Dec 30 01:54:39 2009
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/sipXmediaLib-msvc71.vcproj Sat
Jan 15 07:00:40 2011
@@ -132,6 +132,7 @@
RelativePath=".\src\mp\MpArrayBuf.cpp"
>
</File>
+ <File RelativePath=".\src\mp\MpAsyncPortAudioStream.cpp"/>
<File
RelativePath=".\src\mp\mpau.cpp"
>
@@ -372,10 +373,7 @@
RelativePath=".\src\mp\MpPortAudioMixer.cpp"
>
</File>
- <File
- RelativePath=".\src\mp\MpPortAudioStream.cpp"
- >
- </File>
+ <File RelativePath=".\src\mp\MpPortAudioStreamBase.cpp"/>
<File
RelativePath=".\src\mp\MprAudioFrameBuffer.cpp"
>
@@ -524,6 +522,7 @@
RelativePath=".\src\mp\MpSipxDecoders.cpp"
>
</File>
+ <File RelativePath=".\src\mp\MpSyncPortAudioStream.cpp"/>
<File
RelativePath=".\src\mp\MpStreamFeeder.cpp"
>
@@ -713,6 +712,7 @@
RelativePath=".\include\mp\MpArrayBuf.h"
>
</File>
+ <File RelativePath=".\include\mp\MpAsyncPortAudioStream.h"/>
<File
RelativePath=".\include\mp\mpau.h"
>
@@ -993,10 +993,7 @@
RelativePath=".\include\mp\MpPortAudioMixer.h"
>
</File>
- <File
- RelativePath=".\include\mp\MpPortAudioStream.h"
- >
- </File>
+ <File RelativePath=".\include\mp\MpPortAudioStreamBase.h"/>
<File
RelativePath=".\include\mp\MpQueuePlayerListener.h"
>
@@ -1205,6 +1202,7 @@
RelativePath=".\include\mp\MpSipxDecoders.h"
>
</File>
+ <File RelativePath=".\include\mp\MpSyncPortAudioStream.h"/>
<File
RelativePath=".\include\mp\MpStreamFeeder.h"
>
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/sipXmediaLib-msvc8.vcproj Wed Dec
30 01:54:39 2009
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/sipXmediaLib-msvc8.vcproj Sat Jan
15 07:00:40 2011
@@ -1064,6 +1064,7 @@
RelativePath=".\src\mp\MpArrayBuf.cpp"
>
</File>
+ <File RelativePath=".\src\mp\MpAsyncPortAudioStream.cpp"/>
<File
RelativePath=".\src\mp\mpau.cpp"
>
@@ -1304,10 +1305,7 @@
RelativePath=".\src\mp\MpPortAudioMixer.cpp"
>
</File>
- <File
- RelativePath=".\src\mp\MpPortAudioStream.cpp"
- >
- </File>
+ <File RelativePath=".\src\mp\MpPortAudioStreamBase.cpp"/>
<File
RelativePath=".\src\mp\MprAudioFrameBuffer.cpp"
>
@@ -1456,6 +1454,7 @@
RelativePath=".\src\mp\MpSipxDecoders.cpp"
>
</File>
+ <File RelativePath=".\src\mp\MpSyncPortAudioStream.cpp"/>
<File
RelativePath=".\src\mp\MpStreamFeeder.cpp"
>
@@ -1645,6 +1644,7 @@
RelativePath=".\include\mp\MpArrayBuf.h"
>
</File>
+ <File RelativePath=".\include\mp\MpAsyncPortAudioStream.h"/>
<File
RelativePath=".\include\mp\mpau.h"
>
@@ -1925,10 +1925,7 @@
RelativePath=".\include\mp\MpPortAudioMixer.h"
>
</File>
- <File
- RelativePath=".\include\mp\MpPortAudioStream.h"
- >
- </File>
+ <File RelativePath=".\include\mp\MpPortAudioStreamBase.h"/>
<File
RelativePath=".\include\mp\MpQueuePlayerListener.h"
>
@@ -2137,6 +2134,7 @@
RelativePath=".\include\mp\MpSipxDecoders.h"
>
</File>
+ <File RelativePath=".\include\mp\MpSyncPortAudioStream.h"/>
<File
RelativePath=".\include\mp\MpStreamFeeder.h"
>
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/Makefile.am Wed Dec 30
01:54:39 2009
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/Makefile.am Sat Jan 15
07:00:40 2011
@@ -53,6 +53,7 @@
mp/FilterBank.cpp \
mp/HandsetFilterBank.cpp \
mp/MpArrayBuf.cpp \
+ mp/MpAsyncPortAudioStream.cpp \
mp/MpAudioAbstract.cpp \
mp/MpAudioBuf.cpp \
mp/MpAudioDeviceInfo.cpp \
@@ -95,7 +96,7 @@
mp/MpPlayerEvent.cpp \
mp/MpPortAudioDriver.cpp \
mp/MpPortAudioMixer.cpp \
- mp/MpPortAudioStream.cpp \
+ mp/MpPortAudioStreamBase.cpp \
mp/MpRawAudioBuffer.cpp \
mp/MpResNotificationMsg.cpp \
mp/MpResource.cpp \
@@ -115,6 +116,7 @@
mp/MpStreamPlaylistPlayer.cpp \
mp/MpStreamQueuePlayer.cpp \
mp/MpTopologyGraph.cpp \
+ mp/MpSyncPortAudioStream.cpp \
mp/MpUdpBuf.cpp \
mp/MpdIPPG7231.cpp \
mp/MpdIPPG729.cpp \
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpAudioDriverManager.cpp
Sat Jan 15 06:35:26 2011
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpAudioDriverManager.cpp
Sat Jan 15 07:00:40 2011
@@ -161,7 +161,7 @@
&outputParameters,
MpMisc.m_audioSampleRate,
MpMisc.m_audioSamplesPerFrame,
- MP_AUDIO_STREAM_CLIPOFF,
+ MP_AUDIO_STREAM_DITHEROFF,
TRUE);
if (res != OS_SUCCESS)
{
@@ -242,7 +242,7 @@
&outputParameters,
MpMisc.m_audioSampleRate,
MpMisc.m_audioSamplesPerFrame,
- MP_AUDIO_STREAM_CLIPOFF,
+ MP_AUDIO_STREAM_DITHEROFF,
TRUE);
if (res != OS_SUCCESS)
{
@@ -305,7 +305,7 @@
NULL,
MpMisc.m_audioSampleRate,
MpMisc.m_audioSamplesPerFrame,
- MP_AUDIO_STREAM_CLIPOFF,
+ MP_AUDIO_STREAM_DITHEROFF,
TRUE);
if (res != OS_SUCCESS)
{
@@ -387,7 +387,7 @@
NULL,
MpMisc.m_audioSampleRate,
MpMisc.m_audioSamplesPerFrame,
- MP_AUDIO_STREAM_CLIPOFF,
+ MP_AUDIO_STREAM_DITHEROFF,
TRUE);
if (res != OS_SUCCESS)
{
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioDriver.cpp Wed
Oct 22 12:27:37 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MpPortAudioDriver.cpp Sat
Jan 15 07:00:40 2011
@@ -14,7 +14,8 @@
#include <utl/UtlTypedValue.h>
#include <utl/UtlHashMapIterator.h>
#include "mp/MpPortAudioDriver.h"
-#include "mp/MpPortAudioStream.h"
+#include "mp/MpAsyncPortAudioStream.h"
+#include "mp/MpSyncPortAudioStream.h"
#include "mp/MpAudioStreamInfo.h"
#include "mp/MpAudioStreamParameters.h"
#include "mp/MpPortAudioMixer.h"
@@ -317,16 +318,14 @@

if (numInputChannels > 0 || numOutputChannels > 0)
{
- MpPortAudioStream* strm = NULL;
+ MpPortAudioStreamBase* strm = NULL;

if (!synchronous)
{
- strm = new MpPortAudioStream(numOutputChannels,
- numInputChannels,
- outputSampleFormat,
- inputSampleFormat,
- sampleRate,
- framesPerBuffer);
+ strm = new MpAsyncPortAudioStream(NULL,
+ numOutputChannels, numInputChannels,
+ outputSampleFormat, inputSampleFormat,
+ sampleRate, framesPerBuffer);
}

PaError paError = Pa_OpenStream(stream,
@@ -335,27 +334,25 @@
sampleRate,
framesPerBuffer,
streamFlags,
- synchronous ? NULL : MpPortAudioStream::streamCallback,
+ synchronous ? NULL : MpAsyncPortAudioStream::streamCallback,
strm);

if (paError == paNoError)
{
- if (!synchronous)
- {
- m_audioStreamMap.insertKeyAndValue(new
UtlTypedValue<MpAudioStreamId>(*stream),
- new
UtlPtr<MpPortAudioStream>(strm, TRUE));
- }
- else
- {
- // sync streams will have NULL in the map
- m_audioStreamMap.insertKeyAndValue(new
UtlTypedValue<MpAudioStreamId>(*stream), NULL);
+ if (synchronous)
+ {
+ strm = new MpSyncPortAudioStream(*stream,
+ numOutputChannels, numInputChannels,
+ outputSampleFormat, inputSampleFormat,
+ sampleRate, framesPerBuffer);
}

+ m_audioStreamMap.insertKeyAndValue(new
UtlTypedValue<MpAudioStreamId>(*stream), strm);
status = OS_SUCCESS;
}
else
{
- // delete doesnt mind NULL
+ // delete doesn't mind NULL
delete strm;
}
}
@@ -379,46 +376,40 @@

if ((numInputChannels > 0) || (numOutputChannels > 0))
{
- MpPortAudioStream* strm = NULL;
-
+ MpPortAudioStreamBase* strm = NULL;
+
if (!synchronous)
{
- // we only create representation for asynchronous streams
- strm = new MpPortAudioStream(numOutputChannels,
- numInputChannels,
- sampleFormat,
- sampleFormat,
- sampleRate,
- framesPerBuffer);
- }
-
+ strm = new MpAsyncPortAudioStream(NULL,
+ numOutputChannels, numInputChannels,
+ sampleFormat, sampleFormat,
+ sampleRate, framesPerBuffer);
+ }
+
PaError paError = Pa_OpenDefaultStream(stream,
numInputChannels,
numOutputChannels,
sampleFormat,
sampleRate,
framesPerBuffer,
- synchronous ? NULL : MpPortAudioStream::streamCallback,
+ synchronous ? NULL : MpAsyncPortAudioStream::streamCallback,
strm);

if (paError == paNoError)
{
- if (!synchronous)
- {
- m_audioStreamMap.insertKeyAndValue(new
UtlTypedValue<MpAudioStreamId>(*stream),
- new
UtlPtr<MpPortAudioStream>(strm, TRUE));
- }
- else
- {
- // sync streams will have NULL in the map
- m_audioStreamMap.insertKeyAndValue(new
UtlTypedValue<MpAudioStreamId>(*stream), NULL);
- }
-
+ if (synchronous)
+ {
+ strm = new MpSyncPortAudioStream(*stream,
+ numOutputChannels, numInputChannels,
+ sampleFormat, sampleFormat,
+ sampleRate, framesPerBuffer);
+ }
+ m_audioStreamMap.insertKeyAndValue(new
UtlTypedValue<MpAudioStreamId>(*stream), strm);
status = OS_SUCCESS;
}
else
{
- // delete doesnt mind NULL
+ // delete doesn't mind NULL
delete strm;
}
}
@@ -443,7 +434,7 @@
status = OS_SUCCESS;
}
}
-
+
return status;
}

@@ -461,7 +452,7 @@
status = OS_SUCCESS;
}
}
-
+
return status;
}

@@ -476,10 +467,10 @@

if (paError == paNoError)
{
- resetAsyncStream(stream);
+ resetStreamInternal(stream);
status = OS_SUCCESS;
}
- }
+ }

return status;
}
@@ -495,7 +486,7 @@

if (paError == paNoError)
{
- resetAsyncStream(stream);
+ resetStreamInternal(stream);
status = OS_SUCCESS;
}
}
@@ -555,7 +546,7 @@
status = OS_SUCCESS;
}
}
-
+
return status;
}

@@ -577,7 +568,7 @@
status = OS_SUCCESS;
}
}
-
+
return status;
}

@@ -615,127 +606,53 @@
return status;
}

-OsStatus MpPortAudioDriver::readStreamSync(MpAudioStreamId stream,
- void *buffer,
- unsigned long frames)
+OsStatus MpPortAudioDriver::readStream(MpAudioStreamId stream,
+ void *buffer,
+ unsigned long frames)
{
OsLock lock(ms_driverMutex);
OsStatus status = OS_FAILED;

- // first verify that stream is synchronous
- UtlTypedValue<MpAudioStreamId> strm(stream);
- UtlContainable* res = m_audioStreamMap.find(&strm);
-
- if (res)
- {
- UtlContainable* pValue = m_audioStreamMap.findValue(&strm); // sync
streams have NULL value
-
- if (pValue == NULL)
- {
- // if NULL, stream is synchronous...
- PaError paError = Pa_ReadStream(stream, buffer, frames);
-
- if (paError == paNoError)
- {
- status = OS_SUCCESS;
- }
- else if (paError == paInputOverflowed)
- {
- status = OS_OVERFLOW;
- }
- }
- }
-
- return status;
-}
-
-OsStatus MpPortAudioDriver::writeStreamSync(MpAudioStreamId stream,
- const void *buffer,
- unsigned long frames)
-{
- OsLock lock(ms_driverMutex);
- OsStatus status = OS_FAILED;
-
- // first verify that stream is synchronous
- UtlTypedValue<MpAudioStreamId> strm(stream);
- UtlContainable* res = m_audioStreamMap.find(&strm);
-
- if (res)
- {
- UtlContainable* pValue = m_audioStreamMap.findValue(&strm); // sync
streams have NULL value
-
- if (pValue == NULL)
- {
- // if NULL, stream is synchronous...
- PaError paError = Pa_WriteStream(stream, buffer, frames);
-
- if (paError == paNoError)
- {
- status = OS_SUCCESS;
- }
- else if (paError == paOutputUnderflowed)
- {
- status = OS_OVERFLOW;
- }
- }
- }
-
- return status;
-}
-
-OsStatus MpPortAudioDriver::readStreamAsync(MpAudioStreamId stream,
- void *buffer,
- unsigned long frames)
-{
- OsLock lock(ms_driverMutex);
- OsStatus status = OS_FAILED;
-
if (frames > 0)
{
- // first verify that stream is asynchronous
+ // first lookup the stream
UtlTypedValue<MpAudioStreamId> strm(stream);
UtlContainable* res = m_audioStreamMap.findValue(&strm);

if (res)
{
- // cast to UtlPtr
- UtlPtr<MpPortAudioStream>* pStrmPtr =
(UtlPtr<MpPortAudioStream>*)res;
// get pointer to MpPortAudioStream
- MpPortAudioStream* pStrm = pStrmPtr->getValue();
-
+ MpPortAudioStreamBase* pStrm =
dynamic_cast<MpPortAudioStreamBase*>(res);
if (pStrm)
{
- return pStrm->readStreamAsync(buffer, frames);
- }
- }
- }
-
+ return pStrm->readStream(buffer, frames);
+ }
+ }
+ }
+
return status;
}

-OsStatus MpPortAudioDriver::writeStreamAsync(MpAudioStreamId stream,
- const void *buffer,
- unsigned long frames)
+OsStatus MpPortAudioDriver::writeStream(MpAudioStreamId stream,
+ const void *buffer,
+ unsigned long frames)
{
OsLock lock(ms_driverMutex);
OsStatus status = OS_FAILED;

if (frames > 0)
{
- // first verify that stream is asynchronous
+ // first lookup the stream
UtlTypedValue<MpAudioStreamId> strm(stream);
UtlContainable* res = m_audioStreamMap.findValue(&strm);

if (res)
{
- // cast to UtlPtr
- UtlPtr<MpPortAudioStream>* pStrmPtr =
(UtlPtr<MpPortAudioStream>*)res;
// get pointer to MpPortAudioStream
- MpPortAudioStream* pStrm = pStrmPtr->getValue();
-
+ MpPortAudioStreamBase* pStrm =
dynamic_cast<MpPortAudioStreamBase*>(res);
if (pStrm)
{
- return pStrm->writeStreamAsync(buffer, frames);
+ return pStrm->writeStream(buffer, frames);
}
}
}
@@ -806,17 +723,13 @@
{
OsLock lock(ms_driverMutex);

- // first verify that stream is asynchronous
+ // get stream from map
UtlTypedValue<MpAudioStreamId> strm(stream);
UtlContainable* res = m_audioStreamMap.findValue(&strm);

if (res)
{
- // cast to UtlPtr
- UtlPtr<MpPortAudioStream>* pStrmPtr =
(UtlPtr<MpPortAudioStream>*)res;
- // get pointer to MpPortAudioStream
- MpPortAudioStream* pStrm = pStrmPtr->getValue();
-
+ MpPortAudioStreamBase* pStrm =
dynamic_cast<MpPortAudioStreamBase*>(res);
if (pStrm)
{
volume = pStrm->getInputStreamVolume(type);
@@ -824,7 +737,7 @@
}
}

- return OS_NOT_SUPPORTED;
+ return OS_INVALID_ARGUMENT;
}

OsStatus MpPortAudioDriver::getOutputVolumeMeterReading(MpAudioStreamId
stream,
@@ -833,25 +746,21 @@
{
OsLock lock(ms_driverMutex);

- // first verify that stream is asynchronous
+ // get stream from map
UtlTypedValue<MpAudioStreamId> strm(stream);
UtlContainable* res = m_audioStreamMap.findValue(&strm);

if (res)
{
- // cast to UtlPtr
- UtlPtr<MpPortAudioStream>* pStrmPtr =
(UtlPtr<MpPortAudioStream>*)res;
- // get pointer to MpPortAudioStream
- MpPortAudioStream* pStrm = pStrmPtr->getValue();
-
+ MpPortAudioStreamBase* pStrm =
dynamic_cast<MpPortAudioStreamBase*>(res);
if (pStrm)
{
volume = pStrm->getOutputStreamVolume(type);
return OS_SUCCESS;
- }
+ }
}

- return OS_NOT_SUPPORTED;
+ return OS_INVALID_ARGUMENT;
}

void MpPortAudioDriver::release()
@@ -920,20 +829,17 @@
return NULL;
}

-void MpPortAudioDriver::resetAsyncStream(MpAudioStreamId stream)
+void MpPortAudioDriver::resetStreamInternal(MpAudioStreamId stream)
{
// external lock is assumed

- // first verify that stream is asynchronous
+ // first lookup the stream
UtlTypedValue<MpAudioStreamId> strm(stream);
UtlContainable* res = m_audioStreamMap.findValue(&strm);

if (res)
{
- // cast to UtlPtr
- UtlPtr<MpPortAudioStream>* pStrmPtr =
(UtlPtr<MpPortAudioStream>*)res;
- // get pointer to MpPortAudioStream
- MpPortAudioStream* pStrm = pStrmPtr->getValue();
+ MpPortAudioStreamBase* pStrm =
dynamic_cast<MpPortAudioStreamBase*>(res);
// asynchronous stream needs to be reset after abort
if (pStrm)
{
@@ -947,7 +853,7 @@
// external lock is assumed

UtlTypedValue<MpAudioStreamId> strm(stream);
- UtlContainable* res = m_audioStreamMap.find(&strm); // lookup key not
value, as sync streams have NULL value
+ UtlContainable* res = m_audioStreamMap.find(&strm); // lookup key, if
found stream exists

if (res)
{
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MprFromMic.cpp Sat Jan 15
06:35:26 2011
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MprFromMic.cpp Sat Jan 15
07:00:40 2011
@@ -108,7 +108,7 @@
{
micFrame->setSamplesNumber(MpMisc.m_audioSamplesPerFrame);

- OsStatus res = pAudioDriver->readStreamSync(streamId,
+ OsStatus res = pAudioDriver->readStream(streamId,
micFrame->getSamplesWritePtr(),
MpMisc.m_audioSamplesPerFrame);

=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MprToSpkr.cpp Sat Jan 15
06:35:26 2011
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/mp/MprToSpkr.cpp Sat Jan 15
07:00:40 2011
@@ -92,7 +92,7 @@
MpAudioDriverBase* pAudioDriver = pAudioManager->getAudioDriver();
if (streamId && pAudioDriver)
{
- pAudioDriver->writeStreamSync(streamId, shpSamples, iLength);
+ pAudioDriver->writeStream(streamId, shpSamples, iLength);
}
}

=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpAudioBufTest.cpp
Wed Oct 22 11:32:45 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpAudioBufTest.cpp
Sat Jan 15 07:00:40 2011
@@ -91,10 +91,10 @@
// The frames are identical so tolerance should not make any
difference

// Zero tolerance
- CPPUNIT_ASSERT_EQUAL(frame1.compareSamples(frame2, 0), 0);
+ CPPUNIT_ASSERT_EQUAL(frame1->compareSamples(frame2, 0), 0);

// Tolerance = 2
- CPPUNIT_ASSERT_EQUAL(frame1.compareSamples(frame2, 2), 0);
+ CPPUNIT_ASSERT_EQUAL(frame1->compareSamples(frame2, 2), 0);

// Tweek the samples so there is some difference
samples1[0] +=3;
@@ -103,13 +103,13 @@
samples1[42] +=3;

// Difference greater than tolerance (differ)
- CPPUNIT_ASSERT_EQUAL(frame1.compareSamples(frame2, 2), 1);
+ CPPUNIT_ASSERT_EQUAL(frame1->compareSamples(frame2, 2), 1);

// Difference equal than tolerance (the same)
- CPPUNIT_ASSERT_EQUAL(frame1.compareSamples(frame2, 3), 0);
+ CPPUNIT_ASSERT_EQUAL(frame1->compareSamples(frame2, 3), 0);

// Difference less than tolerance (the same)
- CPPUNIT_ASSERT_EQUAL(frame1.compareSamples(frame2, 5), 0);
+ CPPUNIT_ASSERT_EQUAL(frame1->compareSamples(frame2, 5), 0);
}


=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpFlowGraphTest.cpp
Wed Oct 22 11:32:45 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpFlowGraphTest.cpp
Sat Jan 15 07:00:40 2011
@@ -15,6 +15,7 @@
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

+#include <mp/MpDefs.h>
#include <mp/MpFlowGraphBase.h>
#include <mp/MpTestResource.h>
#include <mp/MpMisc.h>
=======================================
---
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpGenericResourceTest.h
Wed Oct 22 11:32:45 2008
+++
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpGenericResourceTest.h
Sat Jan 15 07:00:40 2011
@@ -14,6 +14,7 @@
#include <mp/MpMediaTask.h>
#include <mp/MpFlowGraphBase.h>
#include <mp/MpTestResource.h>
+#include <mp/MpDefs.h>
#include <mp/MpMisc.h>

#include <cppunit/extensions/HelperMacros.h>
=======================================
---
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpPortAudioDriverTest.cpp
Wed Oct 22 11:32:45 2008
+++
/branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MpPortAudioDriverTest.cpp
Sat Jan 15 07:00:40 2011
@@ -932,7 +932,7 @@

bytesRead = fread(buffer, 1, sampleSize * frames, file);

- res = m_pDriver->writeStreamSync(stream, buffer, frames);
+ res = m_pDriver->writeStream(stream, buffer, frames);
// CPPUNIT_ASSERT(res == OS_SUCCESS);
}
fclose(file);
@@ -994,7 +994,7 @@

for (int i = 0; i < duration; i++)
{
- res = m_pDriver->readStreamSync(stream, pBuffer, frames);
+ res = m_pDriver->readStream(stream, pBuffer, frames);
pBuffer += (sampleSize * frames);
}

@@ -1003,7 +1003,7 @@
// now play back what we recorded
for (int i = 0; i < duration; i++)
{
- res = m_pDriver->writeStreamSync(stream, pBuffer, frames);
+ res = m_pDriver->writeStream(stream, pBuffer, frames);
pBuffer += (sampleSize * frames);
}

@@ -1074,7 +1074,7 @@

bytesRead = fread(buffer, 1, sampleSize * realFrames, file);

- res = m_pDriver->writeStreamSync(stream, buffer, realFrames);
+ res = m_pDriver->writeStream(stream, buffer, realFrames);
cnt++;
}
fclose(file);
@@ -1149,7 +1149,7 @@
realFrames = realFrames * 2;
}

- res = m_pDriver->readStreamSync(stream, pBuffer, realFrames);
+ res = m_pDriver->readStream(stream, pBuffer, realFrames);
pBuffer += (sampleSize * realFrames);
cnt++;
}
@@ -1170,7 +1170,7 @@
realFrames = realFrames * 2;
}

- res = m_pDriver->writeStreamSync(stream, pBuffer, realFrames);
+ res = m_pDriver->writeStream(stream, pBuffer, realFrames);
pBuffer += (sampleSize * realFrames);
cnt++;
}
@@ -1245,7 +1245,7 @@
event.reset();

// now copy data to stream
- m_pDriver->writeStreamAsync(stream, pBuffer, frames);
+ m_pDriver->writeStream(stream, pBuffer, frames);

// repeat until we run out of buffer
pBuffer += sampleSize * frames;
@@ -1333,7 +1333,7 @@
event.reset();

// now copy data to stream
- m_pDriver->writeStreamAsync(stream, pBuffer, realFrames);
+ m_pDriver->writeStream(stream, pBuffer, realFrames);

// repeat until we run out of buffer
pBuffer += sampleSize * realFrames;
@@ -1433,7 +1433,7 @@
event.reset();

// now copy data to stream
- res = m_pDriver->readStreamAsync(stream, pBuffer, frames);
+ res = m_pDriver->readStream(stream, pBuffer, frames);
CPPUNIT_ASSERT(res == OS_SUCCESS || res == OS_UNDERFLOW || res ==
OS_PREFETCH);

if (res == OS_SUCCESS || res == OS_UNDERFLOW)
@@ -1454,7 +1454,7 @@
event.reset();

// now copy data to stream
- res = m_pDriver->writeStreamAsync(stream, pBuffer, frames);
+ res = m_pDriver->writeStream(stream, pBuffer, frames);
CPPUNIT_ASSERT(res == OS_SUCCESS || res == OS_OVERFLOW);

pBuffer += sampleSize * frames;
@@ -1544,7 +1544,7 @@
event.reset();

// now copy data to stream
- res = m_pDriver->readStreamAsync(stream, pBuffer, realFrames);
+ res = m_pDriver->readStream(stream, pBuffer, realFrames);
CPPUNIT_ASSERT(res == OS_SUCCESS || res == OS_UNDERFLOW || res ==
OS_PREFETCH);

if (res == OS_SUCCESS || res == OS_UNDERFLOW)
@@ -1578,7 +1578,7 @@
event.reset();

// now copy data to stream
- res = m_pDriver->writeStreamAsync(stream, pBuffer, realFrames);
+ res = m_pDriver->writeStream(stream, pBuffer, realFrames);
CPPUNIT_ASSERT(res == OS_SUCCESS || res == OS_OVERFLOW);

pBuffer += sampleSize * realFrames;
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MprBridgeTest.cpp Wed
Oct 22 11:32:45 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MprBridgeTest.cpp Sat
Jan 15 07:00:40 2011
@@ -11,6 +11,7 @@
#include <mp/MpMediaTask.h>
#include <mp/MpFlowGraphBase.h>
#include <mp/MpTestResource.h>
+#include <mp/MpDefs.h>
#include <mp/MpMisc.h>
#include <mp/MprBridge.h>
#include <mp/MpBufferMsg.h>
=======================================
--- /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MprToSpkrTest.cpp Wed
Oct 22 11:32:45 2008
+++ /branches/sipxtapi-3.2.1/sipXmediaLib/src/test/mp/MprToSpkrTest.cpp Sat
Jan 15 07:00:40 2011
@@ -209,7 +209,7 @@
CPPUNIT_ASSERT(echoBuf.isValid()); // echo buffer is a clone of
output buffer
MpAudioBufPtr pEchoQBuf = echoBuf;
MpAudioBufPtr pSourceBuf = pBuf;
- CPPUNIT_ASSERT(pSourceBuf.compareSamples(pEchoQBuf) == 0); //
samples must be equal by content
+ CPPUNIT_ASSERT(pSourceBuf->compareSamples(pEchoQBuf) == 0); //
samples must be equal by content

// Buffer is sent to queues and to output
CPPUNIT_ASSERT(mpSinkResource->mLastDoProcessArgs.inBufs[0] ==
pBuf);
@@ -273,7 +273,7 @@
CPPUNIT_ASSERT(echoBuf.isValid()); // echo buffer is a clone of
output buffer
MpAudioBufPtr pEchoQBuf = echoBuf;
MpAudioBufPtr pSourceBuf = pBuf[0];
- CPPUNIT_ASSERT(pSourceBuf.compareSamples(pEchoQBuf) == 0); //
samples must be equal by content
+ CPPUNIT_ASSERT(pSourceBuf->compareSamples(pEchoQBuf) == 0); //
samples must be equal by content

CPPUNIT_ASSERT(mpSinkResource->mLastDoProcessArgs.inBufs[0] ==
pBuf[1]);

Reply all
Reply to author
Forward
0 new messages