summaryrefslogtreecommitdiff
path: root/orkaudio/audiocaptureplugins/sounddevice
diff options
context:
space:
mode:
authorHenri Herscher <henri@oreka.org>2005-10-20 13:40:58 +0000
committerHenri Herscher <henri@oreka.org>2005-10-20 13:40:58 +0000
commit7e1d63dd9fd149e4934bf77095c8610fac786b04 (patch)
tree5fe486a1b0300c3b84fb559107a868e5cc2c95da /orkaudio/audiocaptureplugins/sounddevice
parent467768fc956fc3e5a253373f26c71c681b31b6b8 (diff)
First checkin
git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@2 09dcff7a-b715-0410-9601-b79a96267cd0
Diffstat (limited to 'orkaudio/audiocaptureplugins/sounddevice')
-rw-r--r--orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp252
-rw-r--r--orkaudio/audiocaptureplugins/sounddevice/SoundDevice.dsp130
-rw-r--r--orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.cpp70
-rw-r--r--orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.h60
4 files changed, 512 insertions, 0 deletions
diff --git a/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp b/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp
new file mode 100644
index 0000000..2a6bef4
--- /dev/null
+++ b/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp
@@ -0,0 +1,252 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#define _WINSOCKAPI_ // prevents the inclusion of winsock.h
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Singleton.h"
+#include "ace/Min_Max.h"
+#include "AudioCapturePlugin.h"
+#include "AudioCapturePluginCommon.h"
+#include "portaudio.h"
+#include "Utils.h"
+#include "SoundDeviceConfig.h"
+
+extern AudioChunkCallBackFunction g_audioChunkCallBack;
+extern CaptureEventCallBackFunction g_captureEventCallBack;
+extern LogManager* g_logManager;
+
+SoundDeviceConfigTopObjectRef g_soundDeviceConfigTopObjectRef;
+#define DLLCONFIG g_soundDeviceConfigTopObjectRef.get()->m_config
+
+
+typedef struct
+{
+ PaDeviceID deviceID;
+ int channelCount;
+ PortAudioStream* stream;
+} DeviceUserData;
+
+int portAudioCallBack(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData)
+{
+ DeviceUserData *device = (DeviceUserData *)userData;
+ short * inputSamples = (short *)inputBuffer;
+ CStdString portName;
+
+ if (device->channelCount == 2)
+ {
+ // stereo -> split into two different chunks
+ short* rightBuffer = new short[DLLCONFIG.m_audioChunkSize];
+ short* leftBuffer = new short[DLLCONFIG.m_audioChunkSize];
+
+ for (int sampleId=0; sampleId<DLLCONFIG.m_audioChunkSize ; sampleId++)
+ {
+ rightBuffer[sampleId] = inputSamples[2*sampleId];
+ leftBuffer[sampleId] = inputSamples[2*sampleId+1];
+ }
+ AudioChunkRef chunkRef(new AudioChunk);
+ chunkRef->SetBuffer(rightBuffer, sizeof(short)*framesPerBuffer, AudioChunk::PcmAudio);
+ portName.Format("port%d-%d", device->deviceID, 1);
+ g_audioChunkCallBack(chunkRef, portName);
+
+ chunkRef.reset(new AudioChunk);
+ chunkRef->SetBuffer(leftBuffer, sizeof(short)*framesPerBuffer, AudioChunk::PcmAudio);
+ portName.Format("port%d-%d", device->deviceID, 2);
+ g_audioChunkCallBack(chunkRef, portName);
+
+ delete rightBuffer;
+ delete leftBuffer;
+ }
+ else
+ {
+ // mono
+ AudioChunkRef chunkRef(new AudioChunk);
+ chunkRef->SetBuffer(inputSamples, sizeof(short)*framesPerBuffer, AudioChunk::PcmAudio);
+ portName.Format("port%d", device->deviceID);
+ g_audioChunkCallBack(chunkRef, portName);
+ }
+
+ return 0;
+}
+
+
+class SoundDevice
+{
+public:
+ SoundDevice();
+ void Initialize();
+ void Run();
+ void StartCapture(CStdString& port);
+ void StopCapture(CStdString& port);
+private:
+ DeviceUserData** m_devices;
+ int m_deviceCount;
+ PaStream* m_stream;
+};
+
+typedef ACE_Singleton<SoundDevice, ACE_Thread_Mutex> SoundDeviceSingleton;
+
+SoundDevice::SoundDevice()
+{
+ m_deviceCount = 0;
+ m_devices = NULL;
+}
+
+void Configure(DOMNode* node)
+{
+ if (node)
+ {
+ SoundDeviceConfigTopObjectRef soundDeviceConfigTopObjectRef(new SoundDeviceConfigTopObject);
+ try
+ {
+ soundDeviceConfigTopObjectRef.get()->DeSerializeDom(node);
+ g_soundDeviceConfigTopObjectRef = soundDeviceConfigTopObjectRef;
+ }
+ catch (CStdString& e)
+ {
+ LOG4CXX_WARN(g_logManager->rootLog, "SoundDevice.dll: " + e + " - using defaults");
+ }
+ }
+ else
+ {
+ LOG4CXX_WARN(g_logManager->rootLog, "SoundDevice.dll: got empty DOM tree");
+ }
+}
+
+
+void SoundDevice::Initialize()
+{
+ LOG4CXX_INFO(g_logManager->rootLog, "Initializing Sound Device plugin");
+
+ // create a default config object in case it was not properly initialized by Configure
+ if(!g_soundDeviceConfigTopObjectRef.get())
+ {
+ g_soundDeviceConfigTopObjectRef.reset(new SoundDeviceConfigTopObject);
+ }
+
+
+ PaError result = Pa_Initialize();
+ if (result)
+ {
+ LOG4CXX_ERROR(g_logManager->rootLog, "Could not initialize Sound Device plugin");
+ }
+
+ m_deviceCount = Pa_CountDevices();
+ m_devices = new DeviceUserData*[m_deviceCount];
+
+ for( PaDeviceID deviceID=0; deviceID<m_deviceCount; deviceID++ )
+ {
+ const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo( deviceID );
+
+ m_devices[deviceID] = new DeviceUserData;
+ m_devices[deviceID]->deviceID = deviceID;
+ m_devices[deviceID]->channelCount = ace_max(deviceInfo->maxInputChannels,2);
+ m_devices[deviceID]->stream = NULL;
+ CStdString deviceName(deviceInfo->name);
+
+ if (deviceInfo->maxInputChannels > 0 && deviceName.Find("Primary") == -1) // Primary audio device is a duplicate of one of the devices
+ {
+ CStdString capturePorts;
+ if (deviceInfo->maxInputChannels > 1)
+ {
+ capturePorts.Format("port%d-1, port%d-2", deviceID, deviceID); // stereo
+ }
+ else
+ {
+ capturePorts.Format("port%d-1", deviceID); // mono
+ }
+
+ CStdString maxInputChannelsString = IntToString(deviceInfo->maxInputChannels);
+ LOG4CXX_INFO(g_logManager->rootLog, "Ports:" + capturePorts + " Name:" + deviceName + " Channels:" + maxInputChannelsString);
+
+ result = Pa_OpenStream( &m_devices[deviceID]->stream,
+ deviceID,
+ m_devices[deviceID]->channelCount,
+ paInt16,
+ NULL,
+ paNoDevice ,
+ 0,
+ paInt16,
+ NULL,
+ 8000.0,
+ DLLCONFIG.m_audioChunkSize,
+ 0,
+ 0,
+ portAudioCallBack,
+ (void*)m_devices[deviceID] );
+
+ if (result)
+ {
+ CStdString deviceIdString = IntToString(deviceID);
+ LOG4CXX_ERROR(g_logManager->rootLog, "Device:" + deviceIdString + CStdString(" Pa_OpenStream error:") + Pa_GetErrorText(result));
+ }
+ }
+ }
+}
+
+void SoundDevice::Run()
+{
+ for( PaDeviceID deviceID=0; deviceID<m_deviceCount; deviceID++ )
+ {
+ if (m_devices[deviceID]->channelCount > 0 && m_devices[deviceID]->stream)
+ {
+ PaError result = Pa_StartStream(m_devices[deviceID]->stream);
+ if (result)
+ {
+ CStdString deviceIdString = IntToString(deviceID);
+ LOG4CXX_ERROR(g_logManager->rootLog, "Device:" + deviceIdString + CStdString(" Pa_StartStream error:") + Pa_GetErrorText(result));
+ }
+ }
+ }
+}
+
+void SoundDevice::StartCapture(CStdString& port)
+{
+ CaptureEventRef startEvent(new CaptureEvent);
+ startEvent->m_type = CaptureEvent::EtStart;
+ startEvent->m_timestamp = time(NULL);
+ g_captureEventCallBack(startEvent, port);
+}
+
+void SoundDevice::StopCapture(CStdString& port)
+{
+ CaptureEventRef stopEvent(new CaptureEvent);
+ stopEvent->m_type = CaptureEvent::EtStop;
+ stopEvent->m_timestamp = time(NULL);
+ g_captureEventCallBack(stopEvent, port);
+}
+
+void __CDECL__ Initialize()
+{
+ SoundDeviceSingleton::instance()->Initialize();
+}
+
+void __CDECL__ Run()
+{
+ SoundDeviceSingleton::instance()->Run();
+ for(;;)
+ {
+ // if this idle thread is missing, it will crash winmm
+ ACE_OS::sleep(5);
+ }
+}
+
+void __CDECL__ StartCapture(CStdString& capturePort)
+{
+ SoundDeviceSingleton::instance()->StartCapture(capturePort);
+}
+
+void __CDECL__ StopCapture(CStdString& capturePort)
+{
+ SoundDeviceSingleton::instance()->StopCapture(capturePort);
+} \ No newline at end of file
diff --git a/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.dsp b/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.dsp
new file mode 100644
index 0000000..844f5a6
--- /dev/null
+++ b/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="SoundDevice" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=SoundDevice - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "SoundDevice.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "SoundDevice.mak" CFG="SoundDevice - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SoundDevice - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SoundDevice - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "SoundDevice - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOUNDDEVICE_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../.." /I "../../../OrkBaseCxx" /I "C:\devExt\boost\boost_1_32_0" /I "C:\devExt\portaudio_v18\pa_common" /I "C:\devExt\ACE_wrappers" /I "C:\devExt\xerces++\xerces-c_2_6_0-windows_nt-msvc_60\include" /I "../Common" /I "C:\devExt\log4cxx\log4cxx-0.9.7\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOUNDDEVICE_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 OrkBase.lib winmm.lib dsound.lib ace.lib PAStaticDS.lib log4cxx.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"../../../OrkBaseCxx/Release" /libpath:"C:\devExt\log4cxx\log4cxx-0.9.7\msvc\Lib\Release" /libpath:"C:\devExt\portaudio_v18\winproj\Lib" /libpath:"C:\devExt\ACE_wrappers\lib"
+
+!ELSEIF "$(CFG)" == "SoundDevice - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOUNDDEVICE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../.." /I "../../../OrkBaseCxx" /I "C:\devExt\boost\boost_1_32_0" /I "C:\devExt\portaudio_v18\pa_common" /I "C:\devExt\ACE_wrappers" /I "C:\devExt\xerces++\xerces-c_2_6_0-windows_nt-msvc_60\include" /I "../Common" /I "C:\devExt\log4cxx\log4cxx-0.9.7\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOUNDDEVICE_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 OrkBaseD.lib winmm.lib dsound.lib aced.lib PAStaticDSD.lib log4cxx.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../OrkBaseCxx/Debug" /libpath:"C:\devExt\log4cxx\log4cxx-0.9.7\msvc\Lib\Debug" /libpath:"C:\devExt\portaudio_v18\winproj\Lib" /libpath:"C:\devExt\ACE_wrappers\lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SoundDevice - Win32 Release"
+# Name "SoundDevice - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\AudioCapturePlugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\AudioCapturePluginCommon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\AudioCapturePluginCommon.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ConfigManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SoundDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SoundDeviceConfig.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SoundDeviceConfig.h
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.cpp b/orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.cpp
new file mode 100644
index 0000000..998eb72
--- /dev/null
+++ b/orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.cpp
@@ -0,0 +1,70 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#define _WINSOCKAPI_ // prevents the inclusion of winsock.h
+
+#include "Utils.h"
+#include "Serializers/Serializer.h"
+#include "SoundDeviceConfig.h"
+
+SoundDeviceConfig::SoundDeviceConfig()
+{
+ m_audioChunkSize = AUDIO_CHUNK_SIZE_DEFAULT;
+}
+
+void SoundDeviceConfig::Define(Serializer* s)
+{
+ s->IntValue(AUDIO_CHUNK_SIZE_PARAM, m_audioChunkSize);
+}
+
+void SoundDeviceConfig::Validate()
+{
+ if(m_audioChunkSize > 80000 || m_audioChunkSize<100)
+ {
+ CStdString audioChunkSizeString = IntToString(m_audioChunkSize);
+ throw(CStdString("SoundDeviceConfig: ") + AUDIO_CHUNK_SIZE_PARAM + "=" + audioChunkSizeString + " this is out of range");
+ }
+}
+
+CStdString SoundDeviceConfig::GetClassName()
+{
+ return CStdString("SoundDeviceConfig");
+}
+
+ObjectRef SoundDeviceConfig::NewInstance()
+{
+ return ObjectRef(new SoundDeviceConfig);
+}
+
+//====================================
+
+
+void SoundDeviceConfigTopObject::Define(Serializer* s)
+{
+ s->ObjectValue(SOUND_DEVICE_CONFIG_PARAM, m_config, true);
+}
+
+void SoundDeviceConfigTopObject::Validate()
+{
+ ;
+}
+
+CStdString SoundDeviceConfigTopObject::GetClassName()
+{
+ return CStdString("SoundDeviceConfigTopObject");
+}
+
+ObjectRef SoundDeviceConfigTopObject::NewInstance()
+{
+ return ObjectRef(new SoundDeviceConfigTopObject);
+} \ No newline at end of file
diff --git a/orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.h b/orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.h
new file mode 100644
index 0000000..6453523
--- /dev/null
+++ b/orkaudio/audiocaptureplugins/sounddevice/SoundDeviceConfig.h
@@ -0,0 +1,60 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef __SOUNDDEVICECONFIG_H__
+#define __SOUNDDEVICECONFIG_H__
+
+#include "StdString.h"
+#include "Object.h"
+#include "boost/shared_ptr.hpp"
+
+#define AUDIO_CHUNK_SIZE_PARAM "AudioChunkSize"
+#define AUDIO_CHUNK_SIZE_DEFAULT 8000
+
+/** This class defines various configuration parameters for the generator. */
+class SoundDeviceConfig : public Object
+{
+public:
+ SoundDeviceConfig();
+ void Define(Serializer* s);
+ void Validate();
+
+ CStdString GetClassName();
+ ObjectRef NewInstance();
+ inline ObjectRef Process() {return ObjectRef();};
+
+ int m_audioChunkSize;
+};
+
+//========================================
+
+#define SOUND_DEVICE_CONFIG_PARAM "SoundDevicePlugin"
+
+/** This class represents the top of the configuration hierarchy for the generator. */
+class SoundDeviceConfigTopObject : public Object
+{
+public:
+ void Define(Serializer* s);
+ void Validate();
+
+ CStdString GetClassName();
+ ObjectRef NewInstance();
+ inline ObjectRef Process() {return ObjectRef();};
+
+ SoundDeviceConfig m_config;
+};
+
+typedef boost::shared_ptr<SoundDeviceConfigTopObject> SoundDeviceConfigTopObjectRef;
+
+
+#endif \ No newline at end of file