summaryrefslogtreecommitdiff
path: root/audio
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit8fc5a7f51e62cb4ae44a27bdf4176d04adc80ede (patch)
treeabe4f8fc84569829299f1bd8d22a32b895117813 /audio
downloadsrec-8fc5a7f51e62cb4ae44a27bdf4176d04adc80ede.tar.gz
Initial Contributionandroid-1.0
Diffstat (limited to 'audio')
-rw-r--r--audio/Android.mk1
-rw-r--r--audio/AudioIn/Android.mk1
-rw-r--r--audio/AudioIn/UNIX/Android.mk1
-rw-r--r--audio/AudioIn/UNIX/include/audioin.h262
-rw-r--r--audio/AudioIn/UNIX/include/audioinerr.h128
-rw-r--r--audio/AudioIn/UNIX/include/audioinwrapper.h43
-rw-r--r--audio/AudioIn/UNIX/include/filter.h61
-rw-r--r--audio/AudioIn/UNIX/src/Android.mk26
-rw-r--r--audio/AudioIn/UNIX/src/audioin.c1442
-rw-r--r--audio/AudioIn/UNIX/src/audioinwrapper.cpp276
-rw-r--r--audio/AudioIn/UNIX/src/filter.c376
-rw-r--r--audio/test/Android.mk1
-rw-r--r--audio/test/AudioHardwareRecord/Android.mk29
-rw-r--r--audio/test/AudioHardwareRecord/src/AudioHardwareRecord.c99
-rw-r--r--audio/test/AudioHardwareRecordLoop/Android.mk29
-rw-r--r--audio/test/AudioHardwareRecordLoop/src/AudioHardwareRecordLoop.c140
-rw-r--r--audio/test/AudioInRecord/Android.mk29
-rw-r--r--audio/test/AudioInRecord/src/AudioInRecord.c147
18 files changed, 3091 insertions, 0 deletions
diff --git a/audio/Android.mk b/audio/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/audio/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/audio/AudioIn/Android.mk b/audio/AudioIn/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/audio/AudioIn/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/audio/AudioIn/UNIX/Android.mk b/audio/AudioIn/UNIX/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/audio/AudioIn/UNIX/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/audio/AudioIn/UNIX/include/audioin.h b/audio/AudioIn/UNIX/include/audioin.h
new file mode 100644
index 0000000..3475ceb
--- /dev/null
+++ b/audio/AudioIn/UNIX/include/audioin.h
@@ -0,0 +1,262 @@
+/*---------------------------------------------------------------------------*
+ * audioin.h *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#ifndef __AUDIOIN_H__
+#define __AUDIOIN_H__
+/* -------------------------------------------------------------------------+
+ | ScanSoft Inc. |
+ + -------------------------------------------------------------------------*/
+
+
+
+/* -------------------------------------------------------------------------+
+ | Project : ScanSoft AudioIn component
+ | Module : AUDIOIN
+ | File name : audioin.h
+ | Description : Interface definition for AUDIOIN
+ | Reference(s) : wavein, audioin.chm, audioin.doc, audioin.hlp
+ | SltGl00001_audioin_gl1.doc
+ | Status : Version 1.2
+ + -------------------------------------------------------------------------*/
+/* Oct/8/2002: Fixes for Windows 2000, and memory leaks. Version 1.1 */
+/* PVP Jan/8/2004: Default audio format changed to 16kHz. Version 2.0 */
+/*--------------------------------------------------------------------------*/
+
+/* @doc AUDIOININTERFACE */
+
+
+#include "audioinerr.h"
+
+#if defined( __cplusplus )
+extern "C"
+{
+#endif
+
+/* -------------------------------------------------------------------------+
+ | MACROS |
+ + -------------------------------------------------------------------------*/
+
+/* none */
+
+/* -------------------------------------------------------------------------+
+ | TYPE DEFINITIONS |
+ + -------------------------------------------------------------------------*/
+
+typedef short audioinSample;
+
+
+/* Type Definitions for SCANSOFT-TYPES (re-definition)*/
+
+/* @type AUDIOIN_H | Handle to an audio-in component.
+ * @comm Type is declared as a void *. The actual implementation is
+ * done by the implementation engineer. */
+typedef void * AUDIOIN_H;
+#define WAVE_MAPPER 0
+/* @enum AUDIOIN_STATUSINFO | Enumerator for the Status Information of the AudioIn component.
+ * @comm The information contained in this definition concerns not only to the status of
+ * the FIFO but also the general status of the audio component.
+ *
+ * @xref <f lh_audioinGetSamples>(), AudioIn Diagram State */
+typedef enum _AUDIOIN_STATUSINFO {
+ AUDIOIN_NORMAL, /* @emem Normal state of the audio buffer. No problems detected while retrieving
+ samples.*/
+ AUDIOIN_TIMEOUT, /* @emem The audio-in component timed out after no audio was received from the
+ audio device. The MMSystem is not providing any more samples, or the
+ lh_audioinGetSamples function may be called much faster than the actual
+ thread filling the buffer (Probable issue with the audio device). This could
+ be fixed by decreasing the number of samples that you want to retrieve or by
+ waiting till samples are available. A time out period is set internally on
+ the audioin implementation. Default of:
+ <nlpar>const DWORD GETSAMPLESTIMEOUT_PERIOD = 10000; (time in milliseconds)*/
+ AUDIOIN_HIGHWATERMARK,/* @emem The buffer has been filled out with 75% or more. A high watermark on
+ the audio buffer has been detected and the buffer could be close to an OVERRUN
+ state.*/
+ AUDIOIN_FIFOOVERRUN, /* @emem The buffer has been overfilled with audio samples. You can still retrieve
+ samples from the FIFO with the lhs_audioinGetSamples function, but the audio-in
+ component will not buffer any new audio into the FIFO. AudioinStop must be
+ called to reset the audio-in component.*/
+ AUDIOIN_FLUSHED, /* @emem The buffer has been overfilled with audio samples. You can no longer retrieve
+ samples from the FIFO, since you already emptied it with lhs_audioinGetSamples.
+ The audio-in component will not buffer any new audio into the FIFO.
+ lhs_audioinStop must be called in the audio-in component since
+ lhs_audioinGetSamples will not longer work.*/
+ AUDIOIN_HWOVERRUN, /* @emem The buffer has been overfilled with audio samples inside the device component
+ (audio device). lhs_audioinStop should be called to reset the contents of the
+ FIFO and the codec. This state is caused by an error in the MMSystem. It is
+ recommended to initialize the audio-in component before retrieving samples
+ again.*/
+} AUDIOIN_STATUSINFO;
+
+
+/* @struct AUDIOIN_INFO | Structure for the AudioIn Information
+ * @comm The AUDIOIN_INFO contains information about several parts of the audio-in component.
+ * It gives information about the FIFO buffering audio and at the same time about the audio
+ * component.
+ *
+ * @xref <f lh_audioinGetSamples>(), AudioIn Diagram State */
+typedef struct _AUDIOIN_INFO{
+ AUDIOIN_STATUSINFO eStatusInfo; /* @field The state in which the audio Buffer of the audio-in component
+ is. This is detailed in AUDIOIN_STATUSINFO. */
+ unsigned long u32SamplesAvailable; /* @field The number of Samples still available in the audio Buffer after
+ lhs_audioinGetSamples is called. This value can help you to
+ detect over-runs in the audio buffer.*/
+} AUDIOIN_INFO;
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+typedef enum _AUDIOIN_MSG {
+ AUDIOIN_MSG_OPEN, // audio device was opened
+ AUDIOIN_MSG_START, // start audio acquisition
+ AUDIOIN_MSG_DATA, // audio samples are available
+ AUDIOIN_MSG_STOP, // stop audio acquisition
+ AUDIOIN_MSG_CLOSE, // audio device was closed
+ AUDIOIN_MSG_INVALID, // bogus
+} AUDIOIN_MSG;
+
+/* callback function for "samples ready" notification */
+typedef void (*pCallbackFunc)(AUDIOIN_H hAudioIn, AUDIOIN_MSG uMsg, void* dwInstance, void* dwParam1, void* dwParam2);
+
+/* data structure passed to callback function; loosely based on Windows' WAVEHDR */
+typedef struct {
+ void *pData;
+ unsigned long nBufferLength;
+ unsigned long nBytesRecorded;
+ AUDIOIN_STATUSINFO status;
+} AUDIOIN_WAVEHDR;
+#endif
+
+/* -------------------------------------------------------------------------+
+| EXTERNAL DATA (+ meaning) |
++ -------------------------------------------------------------------------*/
+
+/* none */
+
+/* -------------------------------------------------------------------------+
+| GLOBAL FUNCTION PROTOTYPES |
++ -------------------------------------------------------------------------*/
+#if 0
+ LHS_AUDIOIN_ERROR lhs_audioinOpenEx (
+ unsigned long u32AudioInID, /*@parm [in] Audio-in device ID (ranges from 0 to a number of available
+ devices on the system). You can also use the following flag
+ instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a
+ waveform-audio input device capable of recording in the
+ specified format. <bold Header:> Declared in Mmsystem.h from
+ the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /*@parm [in] Frequency of the recognition engine in Hz. */
+ unsigned long u32NbrOfFrames, /*@parm [in] (not used) Number of frames buffered internally */
+ unsigned long u32SamplesPerFrame, /*@parm [in] Size, in samples, of each individual frame. */
+ AUDIOIN_H * phAudioIn /*@parm [out] Handle to the audio-in device */
+ );
+#endif
+
+LHS_AUDIOIN_ERROR lhs_audioinOpen(
+ unsigned long u32AudioInID, /* [in] audio-in device ID (ranges from 0 to a number of available devices on the
+ system). You can also use the following flag instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a waveform-audio input
+ device capable of recording in the specified format. <bold Header:>
+ Declared in Mmsystem.h from the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /* [in] Frequency of the recognition engine in Hz. */
+ AUDIOIN_H * phAudioIn /* [out] Handle to the audio-in device */
+);
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+LHS_AUDIOIN_ERROR lhs_audioinOpenCallback(
+ unsigned long u32AudioInID, /* [in] audio-in device ID (ranges from 0 to a number of available devices on the
+ system). You can also use the following flag instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a waveform-audio input
+ device capable of recording in the specified format. <bold Header:>
+ Declared in Mmsystem.h from the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /* [in] Frequency of the recognition engine in Hz. */
+ unsigned long u32NbrOfSamples, /*[in] <nl><bold Input:> Number of samples requested per callback */
+
+ pCallbackFunc pCallback, /* [in] callback function */
+ void *pCallbackInstance, /* [in] callback instance */
+ AUDIOIN_H * phAudioIn /* [out] Handle to the audio-in device */
+);
+#endif
+
+LHS_AUDIOIN_ERROR lhs_audioinClose(
+ AUDIOIN_H * phAudioIn /*[in] Pointer to the handle of the audio-in device to be closed.*/
+);
+
+LHS_AUDIOIN_ERROR lhs_audioinStart(
+ AUDIOIN_H hAudioIn /*[in] Handle of the audio-in device */
+);
+
+LHS_AUDIOIN_ERROR lhs_audioinStop(
+ AUDIOIN_H hAudioIn /*[in] Handle of the audio-in device*/
+);
+
+LHS_AUDIOIN_ERROR lhs_audioinGetSamples (
+ AUDIOIN_H hAudioIn, /*[in] Handle of the audio-in device */
+ unsigned long * u32NbrOfSamples, /*[in/out] <nl><bold Input:> The requested number of samples to be filled in
+ the pAudioBuffer. Note that the memory used for pBuffer should be large enough
+ to contain the requested number of samples, also note how the u32NbrOfSamples
+ is different than the Buffer size, since each frame has an specific size depending
+ on the audio format.
+ <nl><bold Output:> The actual number of recorded audio samples written in pBuffer.
+ If you pass 0 to this parameter then you may still retrieve the AUDIOIN_STATUSINFO
+ on the audio component. */
+ void * pAudioBuffer, /*[out] Buffer that contains the recorded samples. The memory used for this
+ buffer is allocated by the client. So, it is the responsibility of the client to
+ make sure that this memory can contain the requested number of samples. The memory
+ for this buffer needs also to be freed by the client. */
+ AUDIOIN_INFO * pAudioInInfo /*[out] Information about the audio internal buffer described in
+ AUDIOIN_INFO.*/
+);
+
+
+LHS_AUDIOIN_ERROR lhs_audioinGetVersion(
+ unsigned long * pu32Version /*[out] The version number of the API implementation. */
+);
+
+
+LHS_AUDIOIN_ERROR lhs_audioinGetVolume(
+ AUDIOIN_H hAudioIn, /*[in] Handle of the audio-in device.*/
+ unsigned long * pu32Volume /*[out] Pointer to a variable that will be filled with the current volume
+ (normally range of 0 - 65535). Depending on the platform the volume
+ value may be set to in sizes of 16, 32 or other size, the range also
+ depends on the platform (Implementations of this interface may
+ change because of the compatibility of the internal function).*/
+);
+
+LHS_AUDIOIN_ERROR lhs_audioinSetVolume(
+ AUDIOIN_H hAudioIn, /*[in] Handle of the audio-in device.*/
+ unsigned long u32Volume /*[in] The volume to be set (normal range 0-65535). Depending on the
+ platform the volume value may be set to in sizes of 16, 32 or other size,
+ the range also depends on the platform. (Implementations of this interface
+ may change because of the compatibility of the internal function)*/
+);
+
+
+const TCHAR * lhs_audioinErrorGetString(
+ const LHS_AUDIOIN_ERROR Error /*[in] The Error code.*/
+);
+
+
+/* -------------------------------------------------------------------------+
+ | END |
+ + -------------------------------------------------------------------------*/
+
+#if defined( __cplusplus )
+}
+#endif
+
+
+#endif /* #ifndef __AUDIOIN_H__ */
diff --git a/audio/AudioIn/UNIX/include/audioinerr.h b/audio/AudioIn/UNIX/include/audioinerr.h
new file mode 100644
index 0000000..9cdefb9
--- /dev/null
+++ b/audio/AudioIn/UNIX/include/audioinerr.h
@@ -0,0 +1,128 @@
+/*---------------------------------------------------------------------------*
+ * audioinerr.h *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _AUDIOINERRAPI_H
+#define _AUDIOINERRAPI_H
+
+/* -------------------------------------------------------------------------+
+ | ScanSoft Inc. |
+ + -------------------------------------------------------------------------*/
+
+
+
+/* -------------------------------------------------------------------------+
+ | Project : ScanSoft AudioIn component
+ | Module : AUDIOINERROR
+ | File name : audioinerr.h
+ | Description : Definition file for the error handling of the AUDIOIN
+ | Reference(s) : wavein, audioin.chm, audioin.doc, audioin.hlp
+ | SltGl00001_audioin_gl1.doc
+ | Status : Version 1.0
+ + -------------------------------------------------------------------------*/
+
+/* @doc AUDIOININTERFACE */
+
+
+
+
+#if defined( __cplusplus )
+extern "C"
+{
+#endif
+
+/* -------------------------------------------------------------------------+
+ | MACROS |
+ + -------------------------------------------------------------------------*/
+
+ /* none */
+
+/* -------------------------------------------------------------------------+
+ | TYPE DEFINITIONS |
+ + -------------------------------------------------------------------------*/
+
+#define TCHAR char
+
+/* @type LHS_AUDIOIN_ERROR | LONG value for Error Code. (i386 win32 wince specific)
+ * @comm Type is declared as a LONG.
+ * @xref LHS_U32, LHS_U16, LHS_BOOL */
+typedef long LHS_AUDIOIN_ERROR;
+
+ /* ERROR CODES */
+
+ /* general errors */
+#define LHS_AUDIOIN_OK 0
+#define LHS_E_AUDIOIN_BASE 1000
+ /* AUDIOIN general errors */
+#define LHS_E_AUDIOIN_NOTIMPLEMENTED (LHS_E_AUDIOIN_BASE+0)
+#define LHS_E_AUDIOIN_NULLPOINTER (LHS_E_AUDIOIN_BASE+1)
+#define LHS_E_AUDIOIN_OUTOFMEMORY (LHS_E_AUDIOIN_BASE+2)
+#define LHS_E_AUDIOIN_INVALIDARG (LHS_E_AUDIOIN_BASE+3)
+ /* AUDIOIN specific errors */
+#define LHS_E_AUDIOIN_INVALIDDEVICEID (LHS_E_AUDIOIN_BASE+4)
+#define LHS_E_AUDIOIN_NOAUDIODRIVER (LHS_E_AUDIOIN_BASE+5)
+#define LHS_E_AUDIOIN_COULDNOTOPENDEVICE (LHS_E_AUDIOIN_BASE+6)
+#define LHS_E_AUDIOIN_BADFORMAT (LHS_E_AUDIOIN_BASE+7)
+#define LHS_E_AUDIOIN_WRONGSTATE (LHS_E_AUDIOIN_BASE+8)
+#define LHS_E_AUDIOIN_OVERRUN (LHS_E_AUDIOIN_BASE+9)
+#define LHS_E_AUDIOIN_NOSAMPLES (LHS_E_AUDIOIN_BASE+10)
+#define LHS_E_AUDIOIN_GETSETVOLUME (LHS_E_AUDIOIN_BASE+11)
+#define LHS_E_AUDIOIN_AUDIOINOPENTIMEDOUT (LHS_E_AUDIOIN_BASE+12)
+#define LHS_E_AUDIOIN_AUDIOINBUSY (LHS_E_AUDIOIN_BASE+13)
+#define LHS_E_AUDIOIN_CREATEEVENTERROR (LHS_E_AUDIOIN_BASE+14)
+#define LHS_E_AUDIOIN_CANNOTRESETAUDIODEV (LHS_E_AUDIOIN_BASE+15)
+#define LHS_E_AUDIOIN_CANNOTCLOSEAUDIODEV (LHS_E_AUDIOIN_BASE+16)
+#define LHS_E_AUDIOIN_CANNOTSTARTAUDIODEV (LHS_E_AUDIOIN_BASE+17)
+#define LHS_E_AUDIOIN_CANNOTSTOPAUDIODEV (LHS_E_AUDIOIN_BASE+18)
+
+// ******************* Error Type Definitions *********************
+typedef struct _AUDIOIN_ERRORINFO
+{
+ long u32ErrorCode;
+
+ const TCHAR *szExplanation;
+
+
+}AUDIOIN_ERRORINFO;
+
+
+/* -------------------------------------------------------------------------+
+| EXTERNAL DATA (+ meaning) |
++ -------------------------------------------------------------------------*/
+
+ /* none */
+
+/* -------------------------------------------------------------------------+
+ | GLOBAL FUNCTION PROTOTYPES |
+ + -------------------------------------------------------------------------*/
+
+#if ( !defined(_MSC_VER) && !defined(WINAPI) )
+#define WINAPI
+#endif
+
+/* -------------------------------------------------------------------------+
+ | END |
+ + -------------------------------------------------------------------------*/
+
+
+#if defined( __cplusplus )
+}
+#endif
+
+#endif /* _AUDIOINERRAPI_H*/
+
diff --git a/audio/AudioIn/UNIX/include/audioinwrapper.h b/audio/AudioIn/UNIX/include/audioinwrapper.h
new file mode 100644
index 0000000..b638c78
--- /dev/null
+++ b/audio/AudioIn/UNIX/include/audioinwrapper.h
@@ -0,0 +1,43 @@
+/*---------------------------------------------------------------------------*
+ * audioinwrapper.h *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#ifndef __AUDIOINWRAPPER_H__
+#define __AUDIOINWRAPPER_H__
+
+#if defined( __cplusplus )
+extern "C"
+{
+#endif
+
+/* -------------------------------------------------------------------------+
+ | C++ FUNCTION WRAPPER |
+ + -------------------------------------------------------------------------*/
+
+int AudioOpen(void);
+int AudioClose(void);
+int AudioSetInputFormat(int sample_rate, int channel_count);
+int AudioRead(short *buffer, int frame_count);
+int AudioSetVolume(int stream_type, int volume);
+int AudioGetVolume(int stream_type);
+
+#if defined( __cplusplus )
+}
+#endif
+
+#endif
diff --git a/audio/AudioIn/UNIX/include/filter.h b/audio/AudioIn/UNIX/include/filter.h
new file mode 100644
index 0000000..41d5ff5
--- /dev/null
+++ b/audio/AudioIn/UNIX/include/filter.h
@@ -0,0 +1,61 @@
+/*---------------------------------------------------------------------------*
+ * filter.h *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#ifndef __FILTER_H__
+#define __FILTER_H__
+
+// Define new data types
+
+typedef short typeSample; // for input and output samples
+typedef short typeCoeff; // FIR filter coefficients
+typedef long typeAccum; // FIR filter accumulator
+
+#define FACTOR_UP 1 // upsampling factor
+#define FACTOR_DOWN 4 // downsampling factor
+
+#define u16ScaleFilterCoeff_up1_down4 15
+
+typedef struct fir_struct
+{
+ int state; // state of FIR delay line (index of next slot to fill)
+ typeSample *z; // pointer to delay line
+
+ unsigned int factor_up;
+ unsigned int factor_down;
+
+ unsigned int nTaps; // length of FIR filter
+ unsigned int scale; // fixed-point filter scale factor
+ const typeCoeff *h; // pointer to FIR filter coefficients
+ typeAccum round; // used for roundoff
+} FIR_struct;
+
+extern const typeCoeff ps16FilterCoeff_up1_down4[];
+
+extern unsigned int filter_length;
+
+extern void FIR_downsample(unsigned int nInput, typeSample *pInput,
+ typeSample *pOutput, FIR_struct *pFIR);
+
+extern FIR_struct* FIR_construct(unsigned int nTaps, const typeCoeff *pCoeffs, int scale, int factor_up, int factor_down);
+
+extern int FIR_deconstruct(FIR_struct *pFIR);
+
+extern void FIR_reset(FIR_struct *pFIR);
+
+#endif
diff --git a/audio/AudioIn/UNIX/src/Android.mk b/audio/AudioIn/UNIX/src/Android.mk
new file mode 100644
index 0000000..2b80e76
--- /dev/null
+++ b/audio/AudioIn/UNIX/src/Android.mk
@@ -0,0 +1,26 @@
+# Copyright 2006 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# common settings for all ASR builds, exports some variables for sub-makes
+include $(ASR_MAKE_DIR)/Makefile.defs
+
+LOCAL_SRC_FILES:= \
+ audioin.c \
+ audioinwrapper.cpp \
+ filter.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../include \
+ $(LOCAL_PATH)/../../../../portable/include \
+
+LOCAL_CFLAGS := \
+
+LOCAL_CFLAGS += \
+ $(ASR_GLOBAL_DEFINES) \
+ $(ASR_GLOBAL_CPPFLAGS) \
+
+LOCAL_MODULE:= libSR_AudioIn
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/audio/AudioIn/UNIX/src/audioin.c b/audio/AudioIn/UNIX/src/audioin.c
new file mode 100644
index 0000000..5d20062
--- /dev/null
+++ b/audio/AudioIn/UNIX/src/audioin.c
@@ -0,0 +1,1442 @@
+/*---------------------------------------------------------------------------*
+ * audioin.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+/* -------------------------------------------------------------------------+
+ | ScanSoft Inc. |
+ + -------------------------------------------------------------------------*/
+
+
+
+/* -------------------------------------------------------------------------+
+ | Project : ScanSoft AudioIn
+ | Module : audioin
+ | File name : audioin.c
+ | Description : This module contains the main implementation for the audioIn
+ | component.
+ | Reference(s) : wavein, audioout, audioin.chm, audioin.doc, audioin.hlp,
+ | SltGl00001_audioin_gl1.doc
+ | Status : Version 1.2
+ + -------------------------------------------------------------------------*/
+/* Feb/25/2002: First QNX/SH4 "draft" version. Version 1.1 */
+/* Nov/25/2004: clean up and minor changes like choice of the codec */
+/* frame size which is now automatically selected */
+/*--------------------------------------------------------------------------*/
+
+#if !defined(ANDROID) || defined(__ARM_ARCH_5__)
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include "plog.h"
+#include "audioin.h"
+
+#if defined(ANDROID)
+#include "audioinwrapper.h"
+#else
+#include <alsa/asoundlib.h>
+#endif
+
+// #define SAVE_RAW_AUDIO 1
+
+#ifdef SAVE_RAW_AUDIO
+#include <sys/time.h>
+#include <stdio.h>
+
+static FILE *audio_data;
+static struct timeval buffer_save_audio;
+#endif
+
+/*#define FILTER_ON*/
+
+#ifdef FILTER_ON
+#include "filter.h"
+#endif
+
+/* -------------------------------------------------------------------------+
+ | EXTERNAL DATA (+ meaning) |
+ + -------------------------------------------------------------------------*/
+
+/* none */
+
+/* -------------------------------------------------------------------------+
+ | MACROS |
+ + -------------------------------------------------------------------------*/
+
+#define NR_OF_CHANNELS 1
+
+#if defined(ANDROID)
+/* size in samples */
+/* We really no longer use this for ANDROID but more changes are needed to remove it. SteveR */
+#define SAMPLES_BUFFER_SIZE (8*1024)
+#define SAMPLES_BUFFER_HIGH_WATERMARK (6*1024)
+#else
+#define SAMPLES_BUFFER_SIZE (50*4410)
+#define SAMPLES_BUFFER_HIGH_WATERMARK (40*4410)
+#endif
+
+/* IMPORTANT NOTE:
+ Here a "frame" is an ALSA term. A frame is comprised of 1 sample if mono,
+ and 2 samples if stereo. This should be distinguished from what the
+ ASR engine and lhs_audioin*() API functions refer to as a frame which is
+ a set of consecutive samples.
+ (see http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html) */
+#if defined(ANDROID)
+#define CODEC_FRAGMENT_SIZE_IN_FRAMES 1024
+#else
+//read the equivalent of 100 ms per buffer. Note: we are recording at 44 kHz
+#define CODEC_FRAGMENT_SIZE_IN_FRAMES 4410
+#endif
+
+/* -------------------------------------------------------------------------+
+ | TYPE DEFINITIONS |
+ + -------------------------------------------------------------------------*/
+
+/* -------------------------------------------------------------------------+
+ | GLOBAL CONSTANTS |
+ + -------------------------------------------------------------------------*/
+
+
+/* -------------------------------------------------------------------------+
+ | GLOBAL VARIABLES |
+ + -------------------------------------------------------------------------*/
+
+#if !defined(ANDROID)
+static snd_pcm_t *ghPCM; /* handle to the PCM recording device */
+#endif
+
+static int gCodecFragmentSizeInFrames = CODEC_FRAGMENT_SIZE_IN_FRAMES; /* fragment size used by the codec driver */
+static audioinSample gSamplesBufferCircularFifo[SAMPLES_BUFFER_SIZE]; /* circular buffer that buffers the incoming samples */
+
+static int gWriteIndexPointer = 0; /* write pointer in the circular FIFO samples buffer */
+static int gReadIndexPointer = 0; /* read pointer in the circular FIFO samples buffer */
+static AUDIOIN_INFO gAudioInInfo; /* to store the info about the acquisition */
+static pthread_mutex_t gAudioMutex; /* to prevent using the read/write pointers at the same time in both threads */
+
+static pthread_cond_t gThreadRunning; /* synchronize when the AcquisitionThreadID is running*/
+static int gThreadRunningSignaled = 0;
+
+static pthread_cond_t gOpenExCalled; /* synchronize when the lhs_audioinOpenEx is called*/
+static int gOpenExCalledSignaled = 0;
+
+static pthread_cond_t gCloseCalled; /* synchronize when the lhs_audioinClose is called*/
+static int gCloseCalledSignaled = 0;
+
+static pthread_t AcquisitionThreadID; /* acquisition thread id */
+
+static int gInitialized = 0; /* did we initialize some of the variables*/
+static int gTerminateThread = 0;
+static struct timeval timer; /* timer used by select to relinquish cpu times */
+
+static int gRecordingVolume = -1; /* recording volume ; number between 0 and 15 */
+static int bRecord = 0; /* recording state is off */
+static int bClose = 1; /* audio pipe is closed */
+
+#ifdef FILTER_ON
+static FIR_struct *pFIR = NULL; /* pointer to FIR structure */
+#endif
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+static pCallbackFunc gpCallback = NULL;
+static void *gpCallbackInstance = NULL;
+static unsigned long gnCallbackSamples = 0;
+#endif
+
+/* -------------------------------------------------------------------------+
+ | LOCAL FUNCTION PROTOTYPES |
+ + -------------------------------------------------------------------------*/
+
+static void *AcquisitionThread(void *data); /* Entry function for the acquisition thread */
+static int OpenAndPrepareSound(unsigned long ulFrequency);
+
+/**
+ * returns 0 if success
+ */
+static int Initialize(AUDIOIN_H * phAudioIn)
+{
+ int doneWaiting = 0;
+
+ if( gInitialized == 1 )
+ return 0;
+
+ /* creates the mutex that will be used to lock/unlock access to some variables/code */
+ if (pthread_mutex_init(&gAudioMutex, NULL) != 0)
+ {
+ return 1;
+ }
+
+ if(pthread_cond_init(&gThreadRunning, 0) != 0 )
+ {
+ return 1;
+ }
+
+ if(pthread_cond_init(&gOpenExCalled, 0) != 0 )
+ {
+ return 1;
+ }
+
+ if(pthread_cond_init(&gCloseCalled, 0) != 0 )
+ {
+ return 1;
+ }
+
+ pthread_mutex_lock(&gAudioMutex);
+
+ /* create a thread with very high priority that will do the acquisition */
+ if (pthread_create(&AcquisitionThreadID, NULL, AcquisitionThread, phAudioIn) != 0)
+ {
+ return 1;
+ }
+
+ //wait for the thread to run
+ while (!doneWaiting)
+ {
+ int rc = pthread_cond_wait(&gThreadRunning, &gAudioMutex);
+ switch (rc)
+ {
+ case 0:
+ if (!gThreadRunningSignaled)
+ {
+ // Avoid spurious wakeups
+ continue;
+ }
+ else
+ {
+ gThreadRunningSignaled = 0;
+ doneWaiting = 1;
+ break;
+ }
+ break;
+ default:
+ pthread_mutex_unlock(&gAudioMutex);
+ return 1;
+ }
+ }
+
+ pthread_mutex_unlock(&gAudioMutex);
+
+
+ //thread is now running.
+
+ gInitialized = 1;
+
+ return 0;
+}
+
+#if 0
+/* disable this unused function for now until we decide what to do with this */
+
+/**
+ * returns 0 if success
+ */
+static int UnInitialize()
+{
+ //signal the thread that it has to stop running.
+ pthread_mutex_lock ( &gAudioMutex );
+ gTerminateThread = 1;
+
+ //signal to tell that our thread is now running.
+ if ( pthread_cond_signal ( &gOpenExCalled ) != 0 )
+ {
+ pthread_mutex_unlock ( &gAudioMutex );
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ return 1;
+ }
+ gOpenExCalledSignaled = 1;
+ pthread_mutex_unlock ( &gAudioMutex );
+
+ /* wait until thread exits */
+ if (pthread_join(AcquisitionThreadID, NULL) != 0)
+ {
+ return 1;
+ }
+
+ /* destroy the mutex */
+ if (pthread_mutex_destroy(&gAudioMutex) !=0 )
+ {
+ return 1;
+ }
+ if( pthread_cond_destroy(&gThreadRunning) != 0 )
+ {
+ return 1;
+ }
+ if( pthread_cond_destroy(&gOpenExCalled) != 0 )
+ {
+ return 1;
+ }
+ if( pthread_cond_destroy(&gCloseCalled) != 0 )
+ {
+ return 1;
+ }
+ gInitialized = 0;
+ return 0;
+}
+#endif
+
+/* -------------------------------------------------------------------------+
+ | LOCAL FUNCTION (should be static) |
+ + -------------------------------------------------------------------------*/
+
+static void setRecordOn(void)
+{
+ bRecord = 1;
+}
+
+static void setRecordOff(void)
+{
+ bRecord = 0;
+}
+
+static int getRecord(void)
+{
+ return bRecord;
+}
+
+static void setCloseOn(void)
+{
+ bClose = 1;
+}
+
+static void setCloseOff(void)
+{
+ bClose = 0;
+}
+
+static int getClose(void)
+{
+ return bClose;
+}
+
+
+/**************************************************************
+ * AcquisitionThread *
+ * *
+ * This function is the entry function of a thread created by *
+ * lhs_audioinOpen and which is responsible of getting the *
+ * samples from the codec and store them in a big circular *
+ * FIFO buffer. *
+ * The priority of this thread has been set to high in order *
+ * to prevent codec buffer overrun. Since the FIFO is limited *
+ * in size (5 sec default ; see SAMPLES_BUFFER_SIZE *
+ * parameter), the application must still be fast enough to *
+ * prevent FIFO overflow/overrun *
+ **************************************************************/
+#if defined(ANDROID)
+
+void *AcquisitionThread ( void *data )
+{
+ int doneWaiting = 0;
+ audioinSample *CodecBuffer;
+ long x;
+ long y;
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ AUDIOIN_H *phAudioIn = (AUDIOIN_H *)data;
+ AUDIOIN_WAVEHDR *pwhdr;
+#endif
+
+
+ pthread_mutex_lock ( &gAudioMutex );
+
+ //signal to tell that our thread is now running.
+ if ( pthread_cond_signal ( &gThreadRunning ) != 0 )
+ {
+ pthread_mutex_unlock ( &gAudioMutex );
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ exit ( 1 );
+ }
+ gThreadRunningSignaled = 1;
+
+ while( 1 )
+ {
+
+ while (!doneWaiting)
+ {
+ int rc = pthread_cond_wait(&gOpenExCalled, &gAudioMutex);
+ switch (rc)
+ {
+ case 0:
+ if (!gOpenExCalledSignaled)
+ {
+ // Avoid spurious wakeups
+ continue;
+ }
+ else
+ {
+ gOpenExCalledSignaled = 0;
+ doneWaiting = 1;
+ break;
+ }
+ break;
+ default:
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ pthread_mutex_unlock(&gAudioMutex);
+ return ( (void *)NULL );
+ }
+ }
+ doneWaiting = 0;
+ pthread_mutex_unlock(&gAudioMutex);
+
+ if( gTerminateThread == 1 )
+ break;
+
+
+
+ /* buffer of 16 bits samples */
+ CodecBuffer = (audioinSample *)malloc ( gCodecFragmentSizeInFrames * sizeof ( audioinSample ) );
+
+ if ( CodecBuffer == NULL )
+ {
+ PLogError ( "Audio In Error malloc\n" );
+ exit ( 1 );
+ }
+ pwhdr = malloc ( sizeof ( AUDIOIN_WAVEHDR ) );
+
+ if ( pwhdr == NULL )
+ {
+ PLogError ( "Audio In Error malloc\n" );
+ exit ( 1 );
+ }
+
+ while ( !getClose ( ) )
+ {
+
+ int iReadFrames = 0; /* number of frames acquired by the codec */
+ /* NOTE: here a frame is comprised of 1 sample if mono, 2 samples if stereo, etc */
+ int iReadSamples = 0; /* number of samples acquired by the codec */
+ int frames_to_read; /* Actual number to read */
+ int frames_read; /* Frames read on one read */
+
+ iReadFrames = 0;
+
+ do
+ {
+ frames_to_read = gCodecFragmentSizeInFrames - iReadFrames;
+ /* AudioRead() - output: number of frames (mono: 1 sample, stereo: 2 samples)*/
+ frames_read = AudioRead ( CodecBuffer + iReadFrames, frames_to_read );
+
+ if ( frames_read > 0 )
+ iReadFrames += frames_read;
+ }
+ while ( ( iReadFrames < gCodecFragmentSizeInFrames ) && ( frames_read > 0 ) );
+ iReadSamples = iReadFrames;
+
+ if ( getRecord ( ) ) /* else continue to read from driver but discard samples */
+ {
+ if ( iReadSamples < 0 )
+ {
+ iReadSamples = 0;
+ gAudioInInfo.eStatusInfo = AUDIOIN_HWOVERRUN;
+ }
+ else
+ {
+#ifdef FILTER_ON
+ /* x: index for start of input samples; y: index for output sample */
+ for ( x = 0, y = 0; x < iReadSamples; x += pFIR->factor_down )
+ {
+ FIR_downsample ( pFIR->factor_down, &( CodecBuffer[x] ), &( CodecBuffer[y++] ), pFIR );
+ }
+ /* update the number samples */
+ iReadSamples = y;
+#endif
+ pthread_mutex_lock ( &gAudioMutex );
+
+ if ( gAudioInInfo.u32SamplesAvailable + iReadSamples > SAMPLES_BUFFER_SIZE )
+ {
+ gAudioInInfo.u32SamplesAvailable = SAMPLES_BUFFER_SIZE;
+ gAudioInInfo.eStatusInfo = AUDIOIN_FIFOOVERRUN;
+ }
+ else
+ {
+ if ( gAudioInInfo.u32SamplesAvailable + iReadSamples > SAMPLES_BUFFER_HIGH_WATERMARK )
+ {
+ gAudioInInfo.eStatusInfo = AUDIOIN_HIGHWATERMARK;
+ }
+ else if ( gAudioInInfo.eStatusInfo != AUDIOIN_FIFOOVERRUN )
+ {
+ gAudioInInfo.eStatusInfo = AUDIOIN_NORMAL;
+ }
+ gAudioInInfo.u32SamplesAvailable += iReadSamples;
+ }
+ if ( gWriteIndexPointer + iReadSamples <= SAMPLES_BUFFER_SIZE )
+ {
+ memcpy ( &( gSamplesBufferCircularFifo[gWriteIndexPointer] ), CodecBuffer,
+ iReadSamples * sizeof ( audioinSample ) );
+ gWriteIndexPointer += iReadSamples;
+
+ if ( gWriteIndexPointer >= SAMPLES_BUFFER_SIZE )
+ gWriteIndexPointer = 0;
+ }
+ else
+ {
+ int NbToCopy;
+
+ NbToCopy = SAMPLES_BUFFER_SIZE - gWriteIndexPointer;
+ memcpy ( &( gSamplesBufferCircularFifo [gWriteIndexPointer] ), CodecBuffer,
+ NbToCopy * sizeof ( audioinSample ) );
+ gWriteIndexPointer = 0;
+ memcpy ( gSamplesBufferCircularFifo, &( CodecBuffer [NbToCopy] ),
+ ( iReadSamples-NbToCopy ) * sizeof ( audioinSample ) );
+ gWriteIndexPointer = iReadSamples - NbToCopy;
+ }
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ /* Callback notification. Ideally this audio acquisition thread should be very lean.
+ It should simply read from the low level driver, store the filtered samples in
+ the FIFO, then go back to reading from the driver. The additional data copy
+ for the callback function is ok despite the overhead incurred, but only because
+ there's some buffering done by the low level driver. This design should be
+ revisited to make it more general purpose.
+ */
+ if ( gpCallback != NULL )
+ {
+ pwhdr->nBufferLength = iReadSamples * sizeof ( audioinSample );
+ pwhdr->nBytesRecorded = pwhdr->nBufferLength;
+ pwhdr->status = AUDIOIN_NORMAL;
+ pwhdr->pData = CodecBuffer;
+ /* pass samples to callback function who should deallocate the buffer and structure */
+ gpCallback ( *phAudioIn, AUDIOIN_MSG_DATA, gpCallbackInstance, pwhdr, NULL );
+ }
+#endif
+ /* samples are available to read */
+ pthread_mutex_unlock ( &gAudioMutex );
+ timer.tv_sec = 0;
+ timer.tv_usec = 200;
+ select ( 0, NULL, NULL, NULL, &timer );
+ }
+ } /* if (getRecord()) */
+
+ } /* while (!getClose()) */
+ if ( AudioClose ( ) !=0 )
+ {
+ PLogError ( "Audio In Error Closing Hardware\n" );
+ }
+ free ( CodecBuffer );
+
+ pthread_mutex_lock ( &gAudioMutex );
+ //signal to tell that our thread is now running.
+ if ( pthread_cond_signal ( &gCloseCalled ) != 0 )
+ {
+ pthread_mutex_unlock ( &gAudioMutex );
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ exit ( 1 );
+ }
+ gCloseCalledSignaled = 1;
+ }
+
+ pthread_exit ( (void *)NULL );
+ return ( (void *)NULL );
+}
+
+#else
+/* non-ANDROID version */
+
+void *AcquisitionThread ( void *data )
+{
+ int doneWaiting = 0;
+ audioinSample *CodecBuffer;
+#ifdef FILTER_ON
+ long x;
+ long y;
+#endif
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ AUDIOIN_H *phAudioIn = (AUDIOIN_H *)data;
+#endif
+
+ pthread_mutex_lock ( &gAudioMutex );
+
+ //signal to tell that our thread is now running.
+ if ( pthread_cond_signal ( &gThreadRunning ) != 0 )
+ {
+ pthread_mutex_unlock ( &gAudioMutex );
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ exit ( 1 );
+ }
+ gThreadRunningSignaled = 1;
+
+ while( 1 )
+ {
+ while (!doneWaiting)
+ {
+ int rc = pthread_cond_wait(&gOpenExCalled, &gAudioMutex);
+ switch (rc)
+ {
+ case 0:
+ if (!gOpenExCalledSignaled)
+ {
+ // Avoid spurious wakeups
+ continue;
+ }
+ else
+ {
+ gOpenExCalledSignaled = 0;
+ doneWaiting = 1;
+ break;
+ }
+ break;
+ default:
+ PLogError ( "Audio In Error pthread_cond_wait\n" );
+ pthread_mutex_unlock(&gAudioMutex);
+ return ( (void *)NULL );
+ }
+ }
+ doneWaiting = 0;
+ pthread_mutex_unlock(&gAudioMutex);
+
+ if( gTerminateThread == 1 )
+ break;
+
+ /* buffer of 16 bits samples */
+ CodecBuffer = (audioinSample *)malloc ( gCodecFragmentSizeInFrames * sizeof ( audioinSample ) );
+
+ if ( CodecBuffer == NULL )
+ {
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ exit ( 1 );
+ }
+
+ while ( !getClose ( ) )
+ {
+ int iReadFrames = 0; /* number of frames acquired by the codec */
+ /* NOTE: here a frame is comprised of 1 sample if mono, 2 samples if stereo, etc */
+ int iReadSamples = 0; /* number of samples acquired by the codec */
+ if ( ( iReadFrames = snd_pcm_readi ( ghPCM, (void *)CodecBuffer, gCodecFragmentSizeInFrames ) ) < 0 )
+ {
+ if ( iReadFrames == -EBADFD )
+ {
+ PLogError ( "Audio In Error PCM Not In The Right State\n" );
+ }
+ else if ( iReadFrames == -EPIPE )
+ {
+ snd_pcm_prepare(ghPCM);
+ PLogError ( "Audio In Error Overrun\n" );
+ }
+ else if ( iReadFrames == -ESTRPIPE )
+ {
+ PLogError ( "Audio In Error Stream Suspended\n" );
+ }
+ }
+ iReadSamples = iReadFrames;
+
+ if ( getRecord ( ) ) /* else continue to read from driver but discard samples */
+ {
+ if ( iReadSamples < 0 )
+ {
+ iReadSamples = 0;
+ gAudioInInfo.eStatusInfo = AUDIOIN_HWOVERRUN;
+ }
+ else
+ {
+#ifdef FILTER_ON
+ /* x: index for start of input samples; y: index for output sample */
+ for ( x = 0, y = 0; x < iReadSamples; x += pFIR->factor_down )
+ {
+ FIR_downsample ( pFIR->factor_down, &( CodecBuffer[x] ), &( CodecBuffer[y++] ), pFIR );
+ }
+ /* update the number samples */
+ iReadSamples = y;
+#endif
+#ifdef SAVE_RAW_AUDIO
+ if ( iReadSamples > 0 )
+ fwrite ( CodecBuffer, 2, iReadSamples, audio_data );
+#endif
+
+ pthread_mutex_lock ( &gAudioMutex );
+
+ if ( gAudioInInfo.u32SamplesAvailable + iReadSamples > SAMPLES_BUFFER_SIZE )
+ {
+ gAudioInInfo.u32SamplesAvailable = SAMPLES_BUFFER_SIZE;
+ gAudioInInfo.eStatusInfo = AUDIOIN_FIFOOVERRUN;
+ }
+ else
+ {
+ if ( gAudioInInfo.u32SamplesAvailable + iReadSamples > SAMPLES_BUFFER_HIGH_WATERMARK )
+ {
+ gAudioInInfo.eStatusInfo = AUDIOIN_HIGHWATERMARK;
+ }
+ else if ( gAudioInInfo.eStatusInfo != AUDIOIN_FIFOOVERRUN )
+ {
+ gAudioInInfo.eStatusInfo = AUDIOIN_NORMAL;
+ }
+ gAudioInInfo.u32SamplesAvailable += iReadSamples;
+ }
+ if ( gWriteIndexPointer + iReadSamples <= SAMPLES_BUFFER_SIZE )
+ {
+ memcpy ( &( gSamplesBufferCircularFifo[gWriteIndexPointer] ), CodecBuffer,
+ iReadSamples * sizeof ( audioinSample ) );
+ gWriteIndexPointer += iReadSamples;
+
+ if ( gWriteIndexPointer >= SAMPLES_BUFFER_SIZE )
+ gWriteIndexPointer = 0;
+ }
+ else
+ {
+ int NbToCopy;
+
+ NbToCopy = SAMPLES_BUFFER_SIZE - gWriteIndexPointer;
+ memcpy ( &( gSamplesBufferCircularFifo [gWriteIndexPointer] ), CodecBuffer,
+ NbToCopy * sizeof ( audioinSample ) );
+ gWriteIndexPointer = 0;
+ memcpy ( gSamplesBufferCircularFifo, &( CodecBuffer [NbToCopy] ),
+ ( iReadSamples-NbToCopy ) * sizeof ( audioinSample ) );
+ gWriteIndexPointer = iReadSamples - NbToCopy;
+ }
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ /* Callback notification. Ideally this audio acquisition thread should be very lean.
+ It should simply read from the low level driver, store the filtered samples in
+ the FIFO, then go back to reading from the driver. The additional data copy
+ for the callback function is ok despite the overhead incurred, but only because
+ there's some buffering done by the low level driver. This design should be
+ revisited to make it more general purpose.
+ */
+ while ( ( gpCallback != NULL ) && ( gAudioInInfo.u32SamplesAvailable >= gnCallbackSamples ) )
+ {
+ AUDIOIN_WAVEHDR *pwhdr;
+
+ pwhdr = malloc ( sizeof ( AUDIOIN_WAVEHDR ) );
+
+ if ( pwhdr != NULL )
+ {
+ pwhdr->nBufferLength = gnCallbackSamples * sizeof ( audioinSample );
+ pwhdr->nBytesRecorded = pwhdr->nBufferLength;
+ pwhdr->status = gAudioInInfo.eStatusInfo;
+ pwhdr->pData = malloc ( pwhdr->nBufferLength );
+
+ if ( pwhdr->pData != NULL )
+ {
+ if ( gReadIndexPointer + gnCallbackSamples <= SAMPLES_BUFFER_SIZE )
+ {
+ memcpy ( pwhdr->pData, &( gSamplesBufferCircularFifo [gReadIndexPointer] ),
+ pwhdr->nBufferLength );
+ gReadIndexPointer += gnCallbackSamples;
+
+ if ( gReadIndexPointer >= SAMPLES_BUFFER_SIZE )
+ gReadIndexPointer = 0;
+ }
+ else
+ {
+ size_t nSamplesPart1 = SAMPLES_BUFFER_SIZE - gReadIndexPointer;
+ size_t nSamplesPart2 = gnCallbackSamples - nSamplesPart1;
+
+ memcpy ( pwhdr->pData, &( gSamplesBufferCircularFifo [gReadIndexPointer] ),
+ nSamplesPart1*sizeof ( audioinSample ) );
+ gReadIndexPointer = 0;
+ memcpy ( pwhdr->pData + nSamplesPart1 * sizeof (audioinSample ),
+ gSamplesBufferCircularFifo, nSamplesPart2 * sizeof ( audioinSample ) );
+ gReadIndexPointer = nSamplesPart2;
+ }
+ gAudioInInfo.u32SamplesAvailable -= gnCallbackSamples;
+ /* pass samples to callback function who should deallocate the buffer and structure */
+ gpCallback ( *phAudioIn, AUDIOIN_MSG_DATA, gpCallbackInstance, pwhdr, NULL );
+ }
+ else
+ {
+ // error
+ }
+ }
+ else
+ {
+ // error
+ }
+ }
+#endif
+ /* samples are available to read */
+ pthread_mutex_unlock ( &gAudioMutex );
+ timer.tv_sec = 0;
+ timer.tv_usec = 200;
+ select ( 0, NULL, NULL, NULL, &timer );
+ }
+ } /* if (getRecord()) */
+
+ } /* while (!getClose()) */
+
+ if ( snd_pcm_close ( ghPCM ) !=0 )
+ {
+ PLogError ( "Audio In Error Closing Hardware\n" );
+ }
+
+ free ( CodecBuffer );
+
+ pthread_mutex_lock ( &gAudioMutex );
+ //signal to tell that our thread is now running.
+ if ( pthread_cond_signal ( &gCloseCalled ) != 0 )
+ {
+ pthread_mutex_unlock ( &gAudioMutex );
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ exit ( 1 );
+ }
+ gCloseCalledSignaled = 1;
+ }
+ pthread_exit ( (void *)NULL );
+ return ( (void *)NULL );
+}
+#endif
+
+/**************************************************************
+ * OpenAndPrepareSound *
+ *************************************************************/
+
+
+static int OpenAndPrepareSound(unsigned long ulFrequency)
+{
+#if defined(ANDROID)
+
+ /* Only support certain frequencies. Modify this to check frequency
+ against a structure of valid frequencies */
+#ifdef FILTER_ON
+ if ( ulFrequency == 11025 )
+ {
+ if ( AudioSetInputFormat ( 44100, NR_OF_CHANNELS ) != 0 ) /* sample at 44100 then downsample */
+ {
+ PLogError ( "Audio In Error OpenAndPrepareSound - AudioSetInputFormat failed!\n");
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+ }
+ else
+ {
+ PLogError ( "Audio In Error OpenAndPrepareSound - invalid frequency!");
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+#else
+ if ( ( ulFrequency == 11025 ) || ( ulFrequency == 8000 ) )
+ {
+ if ( AudioSetInputFormat ( ulFrequency, NR_OF_CHANNELS ) != 0 )
+ {
+ PLogError ( "Audio In Error OpenAndPrepareSound - AudioSetInputFormat failed!");
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+ }
+ else
+ {
+ PLogError ( "Audio In Error OpenAndPrepareSound - invalid frequency!");
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+#endif
+
+ /* set some variables */
+ gAudioInInfo.u32SamplesAvailable = 0;
+
+ /* Open Audio driver */
+ if (AudioOpen() < 0)
+ {
+ PLogError ( "Audio In Error OpenAndPrepareSound - AudioOpen failed!");
+ return ~LHS_AUDIOIN_OK;
+ }
+
+#else
+
+ snd_pcm_hw_params_t *hwparams;
+ unsigned int exact_rate;
+ int dir;
+ int rc;
+
+ /* step 1 : open the sound device */
+ /* ------------------------------ */
+ if ((rc = snd_pcm_open(&ghPCM, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_open() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ if ((rc = snd_pcm_hw_params_malloc(&hwparams)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_malloc() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ /* step 2 : configuring the audio channel */
+ /* -------------------------------------- */
+
+ if ((rc = snd_pcm_hw_params_any(ghPCM, hwparams)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_any() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ if ((rc = snd_pcm_hw_params_set_access(ghPCM, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_set_access() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ if ((rc = snd_pcm_hw_params_set_format(ghPCM, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_set_format() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+#ifdef FILTER_ON
+ if (ulFrequency == 11025)
+ {
+ exact_rate = 44100;
+ }
+ else
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+#else
+ exact_rate = ulFrequency;
+#endif
+
+ dir = 0;
+
+#if 0
+ /* This version seems to have problems when the code is compiled into a shared library.
+ The subsequent call to snd_pcm_hw_params() fails. */
+ if ((rc = snd_pcm_hw_params_set_rate_near(ghPCM, hwparams, &exact_rate, &dir)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_set_rate_near() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+#else
+ /* This version works better and in fact makes more sense. */
+ if ((rc = snd_pcm_hw_params_set_rate(ghPCM, hwparams, exact_rate, dir)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_set_rate() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+#endif
+
+
+ if ((rc = snd_pcm_hw_params_set_channels(ghPCM, hwparams, NR_OF_CHANNELS)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params_set_channels() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ if ((rc = snd_pcm_hw_params(ghPCM, hwparams)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_hw_params() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ /* step 3 : preparing for read */
+ /* --------------------------- */
+
+ /*prepare the channel */
+
+ if ((rc = snd_pcm_prepare(ghPCM)) < 0)
+ {
+ PLogError ( "Audio In Error snd_pcm_prepare() (rc = %d: %s)\n", rc, snd_strerror(rc));
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ /* set some variables */
+ gAudioInInfo.u32SamplesAvailable = 0;
+
+
+#endif
+
+ /* prepare to read samples */
+ setCloseOff();
+
+ return 0;
+}
+
+
+/* -------------------------------------------------------------------------+
+ | GLOBAL FUNCTIONS (prototypes in header file) |
+ + -------------------------------------------------------------------------*/
+
+/**************************************************************
+ * lhs_audioinOpenEx *
+ * *
+ * notes : *
+ * -the input parameters are in fact not used but present *
+ * to ensure compatibility with Win32 implementations *
+ **************************************************************/
+LHS_AUDIOIN_ERROR lhs_audioinOpenEx (
+ unsigned long u32AudioInID, /*@parm [in] Audio-in device ID (ranges from 0 to a number of available
+ devices on the system). You can also use the following flag
+ instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a
+ waveform-audio input device capable of recording in the
+ specified format. <bold Header:> Declared in Mmsystem.h from
+ the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /*@parm [in] Frequency of the recognition engine in Hz. */
+ unsigned long u32NbrOfFrames, /*@parm [in] Number of frames buffered internally. */
+ unsigned long u32SamplesPerFrame, /*@parm [in] Size, in samples, of each individual frame. */
+ AUDIOIN_H * phAudioIn /*@parm [out] Handle to the audio-in device */
+ )
+{
+ //initialize some of the static variables.
+ if( Initialize(phAudioIn) )
+ return ~LHS_AUDIOIN_OK;
+
+
+ /* prepare sound */
+ if (OpenAndPrepareSound(u32Frequency) != 0)
+ {
+ return LHS_E_AUDIOIN_COULDNOTOPENDEVICE;
+ }
+
+ //signal the thread that it has to stop running.
+ pthread_mutex_lock ( &gAudioMutex );
+ //signal to tell that our thread is now running.
+ if ( pthread_cond_signal ( &gOpenExCalled ) != 0 )
+ {
+ pthread_mutex_unlock ( &gAudioMutex );
+ PLogError ( "Audio In Error pthread_cond_signal\n" );
+ exit ( 1 );
+ }
+ gOpenExCalledSignaled = 1;
+ pthread_mutex_unlock ( &gAudioMutex );
+
+#ifdef FILTER_ON
+ /* need to make this more generic to support different filters */
+ pFIR = FIR_construct(filter_length, ps16FilterCoeff_up1_down4, u16ScaleFilterCoeff_up1_down4, FACTOR_UP, FACTOR_DOWN);
+ if (pFIR == NULL)
+ {
+ // TO DO: HANDLE THIS (or modify for static allocation)
+ }
+#endif
+
+ /* set the status to normal */
+ gAudioInInfo.eStatusInfo = AUDIOIN_NORMAL;
+
+ /* do not care, but some applications are checking a NULL handle */
+ *phAudioIn = (void *)10;
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ gpCallback = NULL;
+ gpCallbackInstance = NULL;
+ gnCallbackSamples = 0;
+#endif
+
+ return LHS_AUDIOIN_OK;
+}
+
+/**************************************************************
+ * lhs_audioinOpen *
+ * *
+ * notes : *
+ * -the input parameters are in fact not used but present *
+ * to ensure compatibility with Win32 implementation *
+ **************************************************************/
+LHS_AUDIOIN_ERROR lhs_audioinOpen (
+ unsigned long u32AudioInID, /*@parm [in] Audio-in device ID (ranges from 0 to a number of available
+ devices on the system). You can also use the following flag
+ instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a
+ waveform-audio input device capable of recording in the
+ specified format. <bold Header:> Declared in Mmsystem.h from
+ the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /*@parm [in] Frequency of the recognition engine in Hz. */
+ AUDIOIN_H * phAudioIn /*@parm [out] Handle to the audio-in device */
+ )
+{
+ return lhs_audioinOpenEx(u32AudioInID, u32Frequency, 0, 0, phAudioIn);
+} /* lhs_audioinOpen */
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+/**************************************************************
+ * lhs_audioinOpenCallback *
+ * *
+ * notes : *
+ * -the input parameters are in fact not used but present *
+ * to ensure compatibility with Win32 implementation *
+ **************************************************************/
+LHS_AUDIOIN_ERROR lhs_audioinOpenCallback (
+ unsigned long u32AudioInID, /*@parm [in] Audio-in device ID (ranges from 0 to a number of available
+ devices on the system). You can also use the following flag
+ instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a
+ waveform-audio input device capable of recording in the
+ specified format. <bold Header:> Declared in Mmsystem.h from
+ the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /*@parm [in] Frequency of the recognition engine in Hz. */
+ unsigned long u32NbrOfSamples, /*@parm [in] <nl><bold Input:> Number of samples requested per callback */
+ pCallbackFunc pCallback, /*@parm [in] callback function */
+ void *pCallbackInstance, /*@parm [in] callback instance */
+ AUDIOIN_H * phAudioIn /*@parm [out] Handle to the audio-in device */
+ )
+{
+ LHS_AUDIOIN_ERROR lhsErr;
+
+#ifdef FILTER_ON
+ gCodecFragmentSizeInFrames = u32NbrOfSamples * 4;
+#else
+ gCodecFragmentSizeInFrames = u32NbrOfSamples;
+#endif
+
+ if ((pCallback == NULL) || (u32NbrOfSamples == 0))
+ {
+ return LHS_E_AUDIOIN_INVALIDARG;
+ }
+ lhsErr = lhs_audioinOpenEx(u32AudioInID, u32Frequency, 0, 0, phAudioIn);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ return lhsErr;
+ }
+
+ /* install callback */
+ gpCallback = pCallback;
+ gpCallbackInstance = pCallbackInstance;
+ gnCallbackSamples = u32NbrOfSamples;
+
+ /* callback notification */
+ gpCallback(*phAudioIn, AUDIOIN_MSG_OPEN, gpCallbackInstance, NULL, NULL);
+
+ return LHS_AUDIOIN_OK;
+
+} /* lhs_audioinOpenCallback */
+#endif
+
+/**************************************************************
+ * lhs_audioinClose *
+ * *
+ * notes : *
+ * -the input parameters are in fact not used but present *
+ * to ensure compatibility with Win32 implementations *
+ **************************************************************/
+
+LHS_AUDIOIN_ERROR lhs_audioinClose(AUDIOIN_H *phAudioIn)
+{
+ int doneWaiting = 0;
+
+ /* Validate the handle */
+ if ((phAudioIn == NULL) || (*phAudioIn == NULL))
+ {
+ return LHS_E_AUDIOIN_NULLPOINTER;
+ }
+
+ /* stop recording audio samples */
+ setRecordOff();
+
+ /* stop reading audio samples */
+ setCloseOn();
+
+ //wait for the thread to stop reading samples.
+ pthread_mutex_lock ( &gAudioMutex );
+
+ while (!doneWaiting)
+ {
+ int rc = pthread_cond_wait(&gCloseCalled, &gAudioMutex);
+ switch (rc)
+ {
+ case 0:
+ if (!gCloseCalledSignaled)
+ {
+ // Avoid spurious wakeups
+ continue;
+ }
+ else
+ {
+ gCloseCalledSignaled = 0;
+ doneWaiting = 1;
+ break;
+ }
+ break;
+ default:
+ PLogError ( "Audio In Error pthread_cond_wait\n" );
+ pthread_mutex_unlock(&gAudioMutex);
+ return ~LHS_AUDIOIN_OK;
+ }
+ }
+ pthread_mutex_unlock(&gAudioMutex);
+
+#ifdef FILTER_ON
+ FIR_deconstruct(pFIR);
+#endif
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ /* callback notification */
+ if (gpCallback != NULL) gpCallback(*phAudioIn, AUDIOIN_MSG_CLOSE, gpCallbackInstance, NULL, NULL);
+#endif
+
+ return LHS_AUDIOIN_OK;
+}
+
+/**************************************************************
+ * lhs_audioinStart *
+ * *
+ * notes : *
+ * -the input parameters are in fact not used but present *
+ * to ensure compatibility with Win32 implementations *
+ * -in fact the recording is never stopped or started, when *
+ * non in 'start' status, the samples are just ignored *
+ **************************************************************/
+
+LHS_AUDIOIN_ERROR lhs_audioinStart(AUDIOIN_H hAudioIn)
+{
+#ifdef SAVE_RAW_AUDIO
+ char file_name [256];
+
+ gettimeofday ( &buffer_save_audio, NULL );
+ sprintf ( file_name, "data_%ld_%ld.raw", buffer_save_audio.tv_sec, buffer_save_audio.tv_usec );
+ audio_data = fopen ( file_name, "w" );
+#endif
+ if (hAudioIn == NULL)
+ {
+ return LHS_E_AUDIOIN_NULLPOINTER;
+ }
+
+ pthread_mutex_lock ( &gAudioMutex );
+
+#ifdef FILTER_ON
+ FIR_reset(pFIR);
+#endif
+
+ gWriteIndexPointer = 0;
+ gReadIndexPointer = 0;
+ gAudioInInfo.u32SamplesAvailable = 0;
+
+ /* start recording */
+ setRecordOn();
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ /* callback notification */
+ if (gpCallback != NULL) gpCallback(hAudioIn, AUDIOIN_MSG_START, gpCallbackInstance, NULL, NULL);
+#endif
+ pthread_mutex_unlock ( &gAudioMutex );
+
+ return LHS_AUDIOIN_OK;
+}
+
+/**************************************************************
+ * lhs_audioinStop *
+ * *
+ * notes : *
+ * -the input parameters are in fact not used but present *
+ * to ensure compatibility with Win32 implementations *
+ * -in fact the recording is never stopped or started, when *
+ * non in 'start' status, the samples are just ignored *
+ **************************************************************/
+
+LHS_AUDIOIN_ERROR lhs_audioinStop(AUDIOIN_H hAudioIn)
+{
+#ifdef SAVE_RAW_AUDIO
+ fclose ( audio_data );
+#endif
+ if (hAudioIn == NULL)
+ {
+ return LHS_E_AUDIOIN_NULLPOINTER;
+ }
+ pthread_mutex_lock ( &gAudioMutex );
+
+ /* stop recording (discard samples) */
+ setRecordOff();
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+ /* callback notification */
+ if (gpCallback != NULL) gpCallback(hAudioIn, AUDIOIN_MSG_STOP, gpCallbackInstance, NULL, NULL);
+#endif
+ pthread_mutex_unlock ( &gAudioMutex );
+
+ return LHS_AUDIOIN_OK;
+}
+
+/**************************************************************
+ * lhs_audioinGetSamples *
+ * *
+ * notes : *
+ **************************************************************/
+
+LHS_AUDIOIN_ERROR lhs_audioinGetSamples(AUDIOIN_H hAudioIn, unsigned long * u32NbrOfSamples, void * pAudioBuffer, AUDIOIN_INFO * pgAudioInInfo)
+{
+ unsigned long cSamples;
+ //unsigned long nToCopy;
+
+ /* Check if the handle is valid */
+ if (hAudioIn == NULL)
+ {
+ return LHS_E_AUDIOIN_NULLPOINTER;
+ }
+
+ cSamples = 0;
+
+ while (1)
+ {
+ /* wait until we have enough samples */
+ if (*u32NbrOfSamples <= gAudioInInfo.u32SamplesAvailable)
+ {
+ /* lock the code to prevent dual access to some variables */
+ pthread_mutex_lock(&gAudioMutex);
+
+ /* TO DO: consider copying in chunks (like in AquisitionThread)
+ rather than 1 sample at a time. */
+
+ /* copy all samples into the input buffer */
+ while ((cSamples < *u32NbrOfSamples))
+ {
+ ((audioinSample *)pAudioBuffer)[cSamples++] = gSamplesBufferCircularFifo[gReadIndexPointer++];
+
+ /* adapt the parameters */
+ gAudioInInfo.u32SamplesAvailable -= 1;
+
+ /* adapt circular buffer */
+ if (gReadIndexPointer >= SAMPLES_BUFFER_SIZE)
+ {
+ gReadIndexPointer = 0;
+ }
+
+ /* enough samples */
+ if (cSamples == *u32NbrOfSamples)
+ {
+ /* return the audioin info structure */
+ memcpy(pgAudioInInfo, &gAudioInInfo, sizeof(AUDIOIN_INFO));
+ pthread_mutex_unlock(&gAudioMutex);
+ return LHS_AUDIOIN_OK;
+ }
+ }
+ }
+ else
+ {
+ /* relinquish CPU. select() is more reliable than usleep(). */
+ timer.tv_sec = 0;
+ timer.tv_usec = 10000;
+ select(0, NULL, NULL, NULL, &timer);
+ }
+ } /* while (1) */
+}
+
+/**************************************************************
+ * lhs_audioinGetVersion *
+ * *
+ * notes : not implemented *
+ **************************************************************/
+
+LHS_AUDIOIN_ERROR lhs_audioinGetVersion(unsigned long *pu32Version)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+
+/**************************************************************
+ * lhs_audioinGetVolume/lhs_audioinSetVolume *
+ * *
+ * notes : not implemented *
+ **************************************************************/
+
+LHS_AUDIOIN_ERROR lhs_audioinGetVolume(AUDIOIN_H hAudioIn, unsigned long *pu32Volume)
+{
+ *pu32Volume = gRecordingVolume;
+ return LHS_AUDIOIN_OK;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinSetVolume(AUDIOIN_H hAudioIn, unsigned long u32Volume)
+{
+ gRecordingVolume = u32Volume;
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+/**************************************************************
+ * lhs_audioinErrorGetString *
+ * *
+ * notes : not implemented *
+ **************************************************************/
+
+const char *lhs_audioinErrorGetString(const LHS_AUDIOIN_ERROR Error)
+{
+ return ("unknown error");
+}
+
+
+#else
+/******************************************************************************/
+/* STUB FUNCTIONS FOR SIMULATOR BUILD (DOES NOT SUPPORT THREADS) */
+/* This code is enabled if both ANDROID and __ARM_ARCH_5__ are defined. */
+/******************************************************************************/
+
+#include "audioin.h"
+
+LHS_AUDIOIN_ERROR lhs_audioinOpenEx (
+ unsigned long u32AudioInID, /*@parm [in] Audio-in device ID (ranges from 0 to a number of available
+ devices on the system). You can also use the following flag
+ instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a
+ waveform-audio input device capable of recording in the
+ specified format. <bold Header:> Declared in Mmsystem.h from
+ the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /*@parm [in] Frequency of the recognition engine in Hz. */
+ unsigned long u32NbrOfFrames, /*@parm [in] Number of frames buffered internally. */
+ unsigned long u32SamplesPerFrame, /*@parm [in] Size, in samples, of each individual frame. */
+ AUDIOIN_H * phAudioIn /*@parm [out] Handle to the audio-in device */
+ )
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinOpen (
+ unsigned long u32AudioInID, /*@parm [in] Audio-in device ID (ranges from 0 to a number of available
+ devices on the system). You can also use the following flag
+ instead of a device identifier.
+ <nl><nl><bold WAVE_MAPPER> = The function selects a
+ waveform-audio input device capable of recording in the
+ specified format. <bold Header:> Declared in Mmsystem.h from
+ the Windows Multimedia: Platform SDK.*/
+ unsigned long u32Frequency, /*@parm [in] Frequency of the recognition engine in Hz. */
+ AUDIOIN_H * phAudioIn /*@parm [out] Handle to the audio-in device */
+ )
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+#ifdef AUDIOIN_SUPPORT_CALLBACK
+LHS_AUDIOIN_ERROR lhs_audioinOpenCallback(unsigned long u32AudioInID, unsigned long u32Frequency, unsigned long u32NbrOfSamples, pCallbackFunc pCallback, void* pCallbackInstance, AUDIOIN_H * phAudioIn)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+#endif
+
+LHS_AUDIOIN_ERROR lhs_audioinClose(AUDIOIN_H *phAudioIn)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinStart(AUDIOIN_H hAudioIn)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinStop(AUDIOIN_H hAudioIn)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinGetSamples(AUDIOIN_H hAudioIn, unsigned long * u32NbrOfSamples, void * pAudioBuffer, AUDIOIN_INFO * pgAudioInInfo)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinGetVersion(unsigned long *pu32Version)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinGetVolume(AUDIOIN_H hAudioIn, unsigned long *pu32Volume)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+LHS_AUDIOIN_ERROR lhs_audioinSetVolume(AUDIOIN_H hAudioIn, unsigned long u32Volume)
+{
+ return LHS_E_AUDIOIN_NOTIMPLEMENTED;
+}
+
+const char *lhs_audioinErrorGetString(const LHS_AUDIOIN_ERROR Error)
+{
+ return "LHS_E_AUDIOIN_NOTIMPLEMENTED";
+}
+
+#endif
diff --git a/audio/AudioIn/UNIX/src/audioinwrapper.cpp b/audio/AudioIn/UNIX/src/audioinwrapper.cpp
new file mode 100644
index 0000000..6d3ff99
--- /dev/null
+++ b/audio/AudioIn/UNIX/src/audioinwrapper.cpp
@@ -0,0 +1,276 @@
+/*---------------------------------------------------------------------------*
+ * audioinwrapper.cpp *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+
+#if defined(ANDROID) && defined(__ARM_ARCH_5__)
+
+//#define USE_DEV_EAC_FILE 1
+
+#if defined(USE_DEV_EAC_FILE)
+#include <fcntl.h>
+#define N_CHANNELS 1
+#else
+#include <media/AudioRecord.h>
+#include <media/AudioSystem.h>
+using namespace android;
+#endif
+
+#endif // defined(ANDROID) && defined(__ARM_ARCH_5__)
+
+#include "plog.h"
+
+// #define SAVE_RAW_AUDIO 1
+
+#ifdef SAVE_RAW_AUDIO
+#include <sys/time.h>
+#include <stdio.h>
+
+
+static FILE *audio_data;
+static struct timeval buffer_save_audio;
+#endif
+
+
+// #define MEASURE_SAMPLE_TIMES 1
+
+#ifdef MEASURE_SAMPLE_TIMES
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_SAMPLES_TO_MEASURE 500
+
+static long sample_buffers_received = 0;
+static long total_samples_received = 0;
+static long samples_in_buffer [MAX_SAMPLES_TO_MEASURE];
+static long seconds_buffer_received [MAX_SAMPLES_TO_MEASURE];
+static long micro_seconds_buffer_received [MAX_SAMPLES_TO_MEASURE];
+static struct timeval buffer_received_time;
+
+static void AudioIn_Log_Samples_Received ( void );
+
+static void AudioIn_Log_Samples_Received ( void )
+ {
+ FILE *log_file;
+ char file_name [256];
+ char log_buffer [256];
+ long loop_counter;
+
+ if ( sample_buffers_received > 0 )
+ {
+ gettimeofday ( &buffer_received_time, NULL );
+ sprintf ( file_name, "aud_in_%ld_%ld.txt", buffer_received_time.tv_sec, buffer_received_time.tv_usec );
+ log_file = fopen ( file_name, "w" );
+
+ if ( log_file != NULL )
+ {
+ for ( loop_counter = 0; loop_counter < sample_buffers_received; loop_counter++ )
+ {
+ sprintf ( log_buffer, "%ld %ld %ld %ld\n", loop_counter + 1, samples_in_buffer [loop_counter],
+ seconds_buffer_received [loop_counter], micro_seconds_buffer_received [loop_counter] );
+ fwrite ( log_buffer, 1, strlen ( log_buffer ), log_file );
+ }
+ fclose ( log_file );
+ }
+ sample_buffers_received = 0;
+ }
+ }
+#endif
+
+
+extern "C"
+{
+
+#if defined(ANDROID) && defined(__ARM_ARCH_5__)
+
+#if defined(USE_DEV_EAC_FILE)
+static int audiofd = -1;
+#else
+static AudioRecord* record;
+static int sampleRate = 8000;
+static int numChannels = 1;
+#endif
+
+// called before AudioOpen
+int AudioSetInputFormat(int sample_rate, int channel_count)
+{
+#if defined(USE_DEV_EAC_FILE)
+ return 0;
+#else
+ sampleRate = sample_rate;
+ numChannels = channel_count;
+ return 0;
+#endif
+}
+
+int AudioOpen(void)
+{
+#if defined(USE_DEV_EAC_FILE)
+ audiofd = open("/dev/eac", O_RDONLY, 0666);
+ if (audiofd >= 0) {
+ //fcntl(audiofd, F_SETFL, O_NONBLOCK);
+
+ // possibly lame attempt to get Sooner audio input working
+ struct { unsigned long param1, param2, param3; } params = { 11025, 0, 0 };
+ ioctl(audiofd, 317, &params, sizeof(params));
+ }
+
+ return audiofd;
+#else
+ #ifdef SAVE_RAW_AUDIO
+ char file_name [256];
+
+ gettimeofday ( &buffer_save_audio, NULL );
+ sprintf ( file_name, "data_%ld_%ld.raw", buffer_save_audio.tv_sec, buffer_save_audio.tv_usec );
+ audio_data = fopen ( file_name, "w" );
+ #endif
+ record = new android::AudioRecord(
+ android::AudioRecord::DEFAULT_INPUT, sampleRate,
+ android::AudioSystem::PCM_16_BIT, numChannels, 8, 0);
+
+ if (!record) return -1;
+
+ return record->start() == NO_ERROR ? 0 : -1;
+#endif
+}
+
+int AudioClose(void)
+{
+#if defined(USE_DEV_EAC_FILE)
+ return close(audiofd);
+#else
+ #ifdef MEASURE_SAMPLE_TIMES
+ AudioIn_Log_Samples_Received ( );
+ #endif
+ record->stop();
+ delete record;
+ #ifdef SAVE_RAW_AUDIO
+ fclose ( audio_data );
+ #endif
+ return 0;
+#endif
+}
+
+int AudioRead(short *buffer, int frame_count)
+{
+ int n;
+#if defined(USE_DEV_EAC_FILE)
+ n = read(audiofd, buffer, frame_count*sizeof(short)*N_CHANNELS);
+ n /= sizeof(short)*N_CHANNELS;
+ return n;
+#else
+ int nreq = frame_count * sizeof(short);
+ n = record->read(buffer, nreq);
+ if (n > 0) {
+ if (n != nreq) {
+ PLogError ( "AudioRead error: not enough data %d vs %d\n", n, nreq );
+ }
+ n /= sizeof(short);
+ }
+ #ifdef MEASURE_SAMPLE_TIMES
+ if ( sample_buffers_received < MAX_SAMPLES_TO_MEASURE )
+ {
+ gettimeofday ( &buffer_received_time, NULL );
+ seconds_buffer_received [sample_buffers_received] = buffer_received_time.tv_sec;
+ micro_seconds_buffer_received [sample_buffers_received] = buffer_received_time.tv_usec;
+ samples_in_buffer [sample_buffers_received] = n;
+ total_samples_received += n;
+ sample_buffers_received++;
+ }
+ #endif
+
+ #ifdef SAVE_RAW_AUDIO
+ if ( n > 0 )
+ fwrite ( buffer, 2, n, audio_data );
+ #endif
+ return n;
+#endif
+}
+
+int AudioSetVolume(int stream_type, int volume)
+{
+#if defined(USE_DEV_EAC_FILE)
+ return 0;
+#else
+ return AudioSystem::setStreamVolume(stream_type, (float)volume/100.0f);
+#endif
+}
+
+int AudioGetVolume(int stream_type)
+{
+#if defined(USE_DEV_EAC_FILE)
+ return 0;
+#else
+ float v = 0;
+ AudioSystem::getStreamVolume(stream_type, &v);
+ return int(v * 100.0f);
+#endif
+}
+
+#else
+
+int AudioOpen(void)
+{
+ return -1;
+}
+
+int AudioClose(void)
+{
+ return -1;
+}
+
+int AudioSetInputFormat(int sample_rate, int channel_count)
+{
+ return -1;
+}
+
+int AudioSetOutputFormat(int sample_rate, int channel_count)
+{
+ return -1;
+}
+
+int AudioRead(short *buffer, int frame_count)
+{
+ return -1;
+}
+
+int AudioWrite(short *buffer, int frame_count)
+{
+ return -1;
+}
+
+int AudioSetStreamType(int stream_type)
+{
+ return -1;
+}
+
+int AudioSetVolume(int stream_type, int volume)
+{
+ return -1;
+}
+
+int AudioGetVolume(int stream_type)
+{
+ return -1;
+}
+
+#endif
+
+} // extern "C"
diff --git a/audio/AudioIn/UNIX/src/filter.c b/audio/AudioIn/UNIX/src/filter.c
new file mode 100644
index 0000000..9e983d0
--- /dev/null
+++ b/audio/AudioIn/UNIX/src/filter.c
@@ -0,0 +1,376 @@
+/*---------------------------------------------------------------------------*
+ * filter.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#define _ROUNDOFF
+
+/****************************************************************************
+ * FILENAME
+ * pcm44pcm11.c
+ *
+ * DESCRIPTION
+ *
+ * Apply FIR filter to 44 kHz raw 16-bit PCM linear audio then
+ * downsample to 11 kHz.
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "filter.h"
+
+/****************************************************************************
+ * FIR FILTER *
+ ****************************************************************************/
+
+/* b = firls(120, [0 5000 6000 44000/2]/44000*2, [1 1 0 0]); */
+/* bRounded = round(b*2^15); */
+
+const typeCoeff ps16FilterCoeff_up1_down4[] = {
+
+ 1, 9, 13, 10, -1, -16, -24, -18, 2, 25,
+ 38, 28, -2, -38, -57, -42, 3, 55, 81, 60,
+ -3, -76, -113, -84, 4, 104, 153, 114, -5, -138,
+ -205, -152, 5, 183, 271, 202, -6, -241, -360, -269,
+ 6, 321, 482, 364, -6, -438, -667, -511, 7, 632,
+ 986, 778, -7, -1030, -1704, -1450, 7, 2451, 5204, 7366,
+ 8185, 7366, 5204, 2451, 7, -1450, -1704, -1030, -7, 778,
+ 986, 632, 7, -511, -667, -438, -6, 364, 482, 321,
+ 6, -269, -360, -241, -6, 202, 271, 183, 5, -152,
+ -205, -138, -5, 114, 153, 104, 4, -84, -113, -76,
+ -3, 60, 81, 55, 3, -42, -57, -38, -2, 28,
+ 38, 25, 2, -18, -24, -16, -1, 10, 13, 9,
+ 1,
+};
+unsigned int filter_length = sizeof(ps16FilterCoeff_up1_down4)/sizeof(typeCoeff);
+
+/****************************************************************************
+ * FIR_struct *FIR_construct(unsigned int nTaps, FIR_type *pCoeffs)
+ *
+ * DESCRIPTION
+ * allocate and initialize FIR structure
+ *
+ * INPUT
+ * nTaps - length of FIR filter
+ * pCoeffs - pointer to FIR filter coefficients
+ * scale - fixed point scale factor
+ *
+ * OUTPUT
+ * returns pointer to FIR structure; NULL if error
+ ****************************************************************************/
+FIR_struct* FIR_construct(unsigned int nTaps, const typeCoeff *pCoeffs, int scale, int factor_up, int factor_down)
+{
+FIR_struct *pFIR;
+
+ if (nTaps == 0)
+ return NULL;
+
+ pFIR = malloc(sizeof(FIR_struct));
+ if (pFIR == NULL)
+ return NULL;
+
+ // alloocate space for delay line use calloc to avoid uninitialized memory
+ // that causes an audible "pop" at the beginning of audio. SteveR
+ pFIR->z = calloc(nTaps * sizeof(typeSample), 1);
+ if (pFIR->z == NULL)
+ {
+ free(pFIR);
+ return NULL;
+ }
+
+ pFIR->factor_up = factor_up;
+ pFIR->factor_down = factor_down;
+
+ pFIR->state = 0;
+ pFIR->h = pCoeffs;
+ pFIR->nTaps = nTaps;
+ pFIR->scale = scale;
+ pFIR->round = (1 << (scale-1));
+
+ return pFIR;
+}
+
+/****************************************************************************
+ * int FIR_deconstruct(FIR_struct *pFIR)
+ *
+ * DESCRIPTION
+ * deallocate FIR structure
+ *
+ * INPUT
+ * pFIR - pointer to FIR structure
+ *
+ * OUTPUT
+ * returns 0 for success; 1 for failure
+ ****************************************************************************/
+
+int FIR_deconstruct(FIR_struct *pFIR)
+{
+ if (pFIR == NULL)
+ return 1;
+
+ if (pFIR->z == NULL)
+ return 1;
+
+ free(pFIR->z);
+ free(pFIR);
+
+ return 0;
+}
+
+/****************************************************************************
+ * void FIR_reset(FIR_struct *pFIR)
+ *
+ * DESCRIPTION
+ *
+ * reset FIR state
+ *
+ * INPUT
+ * pFIR - pointer to FIR structure
+ *
+ * OUTPUT
+ * pFIR->state initialized
+ ****************************************************************************/
+
+void FIR_reset(FIR_struct *pFIR)
+{
+ pFIR->state = 0;
+
+ memset(pFIR->z, pFIR->nTaps, sizeof(typeSample));
+}
+
+/*****************************************************************************
+ * FIR_type FIR_downsample(unsigned int nInput, typeSample *pInput,
+ * typeSample *pOutput, FIR_struct *pFIR)
+ *
+ * DESCRIPTION
+ *
+ * Apply FIR filter to input data. If nInput > 1, this will also
+ * decimate by a factor of nInput. That is, the filter will only be
+ * evaluated every nInput samples, not at each of the nInput samples.
+ *
+ * Breakup filter computation into 2 parts to avoid doing a wraparound
+ * check inside the loop.
+ *
+ * Example:
+ *
+ * pFIR->nTaps = 8
+ * pFIR->state = 2
+ * nInput = 1
+ * *pInput = s20
+ *
+ * (a) Store new sample(s) in delay buffer z[]
+ *
+ * Since pFIR->state == 2, store new sample s20 at location z[2]
+ *
+ * *** latest input stored at z[pFIR->state]
+ * *
+ * -------------------------------------------------
+ * z | s14 | s13 | s20 | s19 | s18 | s17 | s16 | s15 |
+ * -------------------------------------------------
+ * h | h0 | h1 | h2 | h3 | h4 | h5 | h6 | h7 |
+ * -------------------------------------------------
+ * 0 1 2 3 4 5 6 7
+ *
+ * (b) Update state to point to newest sample, wrap if < 0
+ *
+ * Since nInput == 1, state for newest sample is still 2
+ * (otherwise, update state -= nInput-1; wrap by adding nTaps if < 0)
+ *
+ * (c) Accumulate "end part" first
+ *
+ * z: start with latest sample at z[pFIR->state], then advance to right
+ * h: start with 1st filter coefficient, then advance to right
+ *
+ * acc = h0*s20 + h1*s19 + h2*s18 + h3*s17 + h4*s16 + h5*s15
+ *
+ * (d) Accumulate "beginning part"
+
+ * z: start with sample at beginning of delay buffer, then advance
+ * to sample before latest one at z[pFIR->state]
+ * h: continue with next filter coefficient from step (a)
+ *
+ * acc += (h6*s14 + h7*s13) FIR filter output
+ * *pOutput = acc
+ *
+ * (e) Update FIR state
+ *
+ * state--, wrapping if < 0 to simulate circular buffer
+ *
+ * INPUT
+ *
+ * nInput - number of new input samples; evaluate FIR at this point
+ * pInput - pointer to input sample buffer
+ * pOutput - pointer to output sample buffer
+ * pFIR - pointer to FIR structure
+ *
+ * OUTPUT
+ *
+ *****************************************************************************/
+
+void FIR_downsample(unsigned int nInput, typeSample *pInput,
+ typeSample *pOutput, FIR_struct *pFIR)
+{
+typeAccum accum;
+typeCoeff const *ph; // pointer to coefficients
+typeSample *pz; // pointer to delay line
+typeSample *pz_beg; // pointer to beginning of delay line
+typeSample *pz_end; // pointer to last slot in delay line
+unsigned int nTaps_end;
+unsigned int nTaps_beg;
+unsigned int i;
+
+ // initialize
+ accum = 0;
+ ph = pFIR->h; // point to coefficients
+ pz_beg = pFIR->z; // start of delay line
+ pz_end = pFIR->z + pFIR->nTaps - 1; // end of delay line
+
+ // (a) Store new input samples in delay line (circular addressing would help a lot)
+ pz = pFIR->z + pFIR->state; // point to next empty slot in delay line
+ for (i = 0; i < nInput; i++)
+ {
+ *pz-- = *pInput++;
+ if (pz < pz_beg)
+ pz = pz_end; // wrap around (circular buffer)
+ }
+
+ // (b) adjust state to reflect addition of samples
+ pFIR->state -= nInput-1;
+ if (pFIR->state < 0)
+ pFIR->state += pFIR->nTaps; // wrap
+
+ // (c) Accumulate "end part"
+ pz = pFIR->z + pFIR->state;
+ nTaps_end = pFIR->nTaps - pFIR->state;
+ for (i = 0; i < nTaps_end; i++)
+ {
+ accum += *ph++ * *pz++;
+ }
+
+ // (d) Accumulate "beginning part"
+ pz = pFIR->z;
+ nTaps_beg = pFIR->state;
+ for (i = 0; i < nTaps_beg; i++)
+ {
+ accum += *ph++ * *pz++;
+ }
+
+ // (e) Update FIR state for next batch of incoming samples
+ pFIR->state--;
+ if (pFIR->state < 0)
+ pFIR->state += pFIR->nTaps; // wrap
+
+#ifdef _ROUNDOFF
+ if (accum >= 0)
+ accum += pFIR->round;
+ else
+ accum -= pFIR->round;
+#endif
+
+ *pOutput = (typeSample) (accum >> pFIR->scale);
+}
+
+#if 0
+/*****************************************************************************
+ * main
+ *****************************************************************************/
+
+int main(int argc, char* argv[])
+{
+FILE *fpInputSamples; // input raw PCM file
+FILE *fpOutputSamples; // output raw PCM file
+
+typeSample s_in[FACTOR_DOWN]; // input samples
+typeSample s_out; // filtered sample
+FIR_struct *pFIR; // pointer to FIR structure
+int nSampleGet; // number of samples to read from input speech file
+int nSampleRead; // number of samples read from input speech file
+unsigned long nSampleTot; // total number of samples read so far
+time_t t0; // time upon entry
+
+ t0 = time(NULL); // get time upon entry
+
+ // Check Command-line Parameters
+ if (argc != 3)
+ {
+ fprintf(stderr, "pcm44pcm11 v1.0\n");
+ fprintf(stderr, " - downsamples 44 kHz to 11 kHz (16-bit PCM, Intel byte order)\n");
+ fprintf(stderr, "Usage: pcm44pcm11 <input PCM file> <output PCM file>\n\n");
+ return 0;
+ }
+
+ // Open input sample file
+ if ((fpInputSamples = fopen(argv[1], "rb")) == NULL)
+ {
+ fprintf(stderr, "Error reading input sample file: %s\n\n", argv[1]);
+ exit(1); // abnormal exit
+ }
+
+ // Create output sample file
+ if ((fpOutputSamples = fopen(argv[2], "wb")) == NULL)
+ {
+ fprintf(stderr, "Error creating output file: %s\n\n", argv[2]);
+ fclose(fpInputSamples);
+ exit(1); // abnormal exit
+ }
+
+ // **************************************************************************************
+ // Begin filtering...
+ // **************************************************************************************
+
+ pFIR = FIR_construct(filter_length,
+ ps16FilterCoeff_up1_down4,
+ u16ScaleFilterCoeff_up1_down4,
+ FACTOR_UP,
+ FACTOR_DOWN);
+
+ fprintf(stdout, "Filtering...\n");
+
+ FIR_reset(pFIR);
+
+ nSampleTot = 0;
+ while (!feof(fpInputSamples))
+ {
+ nSampleGet = pFIR->factor_down; // if downsampling, only filter every factor_down samples
+ nSampleRead = fread(s_in, sizeof(typeSample), nSampleGet, fpInputSamples);
+ if (feof(fpInputSamples) || (nSampleRead != nSampleGet))
+ break; // done with input file
+ nSampleTot += nSampleRead;
+
+ FIR_downsample(nSampleRead, s_in, &s_out, pFIR);
+
+ if (nSampleTot < pFIR->nTaps)
+ continue; // wait until delay buffer has been filled to skip transients
+
+ fwrite(&s_out, sizeof(typeSample), 1, fpOutputSamples);
+ }
+
+ fprintf(stdout, "\n\nTime elapsed: %d sec\n", time(NULL)-t0);
+
+ FIR_deconstruct(pFIR);
+
+ fclose(fpInputSamples);
+ fclose(fpOutputSamples);
+
+ return 0;
+}
+
+#endif
diff --git a/audio/test/Android.mk b/audio/test/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/audio/test/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/audio/test/AudioHardwareRecord/Android.mk b/audio/test/AudioHardwareRecord/Android.mk
new file mode 100644
index 0000000..cfd8b1c
--- /dev/null
+++ b/audio/test/AudioHardwareRecord/Android.mk
@@ -0,0 +1,29 @@
+# Copyright 2006 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# common settings for all ASR builds, exports some variables for sub-makes
+include $(ASR_MAKE_DIR)/Makefile.defs
+
+LOCAL_SRC_FILES:= \
+ src/AudioHardwareRecord.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(ASR_ROOT_DIR)/audio/AudioIn/UNIX/include \
+
+LOCAL_CFLAGS := \
+
+LOCAL_SHARED_LIBRARIES := \
+ libUAPI_jni \
+ libutils \
+ libhardware \
+
+LOCAL_MODULE:= AudioHardwareRecord
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+
+include $(BUILD_EXECUTABLE)
diff --git a/audio/test/AudioHardwareRecord/src/AudioHardwareRecord.c b/audio/test/AudioHardwareRecord/src/AudioHardwareRecord.c
new file mode 100644
index 0000000..49a85fa
--- /dev/null
+++ b/audio/test/AudioHardwareRecord/src/AudioHardwareRecord.c
@@ -0,0 +1,99 @@
+/*---------------------------------------------------------------------------*
+ * AudioHardwareRecord.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include "audioinwrapper.h"
+
+#define SAMPLING_RATE 44100
+
+#define N_FRAMES_PER_BUFFER 512 /* low-level driver counts in terms of frames, not samples */
+#define N_TUPLES_PER_FRAME 1 /* tuple: a set of samples (set of 1 if mono, set of 2 if stereo */
+
+#define N_CHANNELS_PER_TUPLE 1 /* 1: mono; 2: stereo */
+
+#define N_TUPLES_PER_BUFFER (N_FRAMES_PER_BUFFER * N_TUPLES_PER_FRAME)
+#define N_SAMPLES_PER_BUFFER (N_TUPLES_PER_BUFFER * N_CHANNELS_PER_TUPLE)
+
+#define N_SECONDS_TO_RECORD 10
+#define N_SAMPLES_TO_RECORD (SAMPLING_RATE * N_SECONDS_TO_RECORD * N_CHANNELS_PER_TUPLE)
+
+typedef short typeSample;
+
+/* store incoming samples here, then write to file at the end */
+typeSample recordedSamples[N_SAMPLES_TO_RECORD];
+
+
+int main(int argc, char* argv[])
+{
+ int rc;
+ unsigned int i;
+
+ memset(recordedSamples, 0, N_SAMPLES_TO_RECORD * sizeof(typeSample));
+
+ rc = AudioSetInputFormat(SAMPLING_RATE, N_CHANNELS_PER_TUPLE);
+ if (rc != 0)
+ {
+ printf("ERROR: AudioSetInputFormat() returns %d\n", rc);
+ exit(1);
+ }
+
+ rc = AudioOpen();
+ if (rc < 0)
+ {
+ printf("ERROR: AudioOpen() returns %d (device handle/ID)\n", rc);
+ exit(1);
+ }
+
+ i = 0;
+ while (i <= N_SAMPLES_TO_RECORD - N_SAMPLES_PER_BUFFER)
+ {
+ rc = AudioRead(&(recordedSamples[i]), N_FRAMES_PER_BUFFER);
+ if (rc > 0)
+ i += (rc * N_TUPLES_PER_FRAME * N_CHANNELS_PER_TUPLE);
+ else
+ printf("ERROR: AudioRead() returns %d\n", rc);
+ }
+
+ rc = AudioClose();
+ if (rc != 0)
+ {
+ printf("ERROR: AudioClose() returns %d\n", rc);
+ exit(1);
+ }
+
+ /* write to file */
+ {
+ FILE *fpOutput;
+ char *szFilename = "output_AudioHardwareRecord.pcm";
+
+ fpOutput = fopen(szFilename, "wb");
+ if (fpOutput == NULL)
+ {
+ printf("ERROR: cannot create '%s'\n", szFilename);
+ exit(1);
+ }
+ fwrite(recordedSamples, sizeof(typeSample), i, fpOutput);
+ fclose(fpOutput);
+ }
+
+ return 0;
+}
diff --git a/audio/test/AudioHardwareRecordLoop/Android.mk b/audio/test/AudioHardwareRecordLoop/Android.mk
new file mode 100644
index 0000000..b7fab3a
--- /dev/null
+++ b/audio/test/AudioHardwareRecordLoop/Android.mk
@@ -0,0 +1,29 @@
+# Copyright 2006 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# common settings for all ASR builds, exports some variables for sub-makes
+include $(ASR_MAKE_DIR)/Makefile.defs
+
+LOCAL_SRC_FILES:= \
+ src/AudioHardwareRecordLoop.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(ASR_ROOT_DIR)/audio/AudioIn/UNIX/include \
+
+LOCAL_CFLAGS := \
+
+LOCAL_SHARED_LIBRARIES := \
+ libUAPI_jni \
+ libutils \
+ libhardware \
+
+LOCAL_MODULE:= AudioHardwareRecordLoop
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+
+include $(BUILD_EXECUTABLE)
diff --git a/audio/test/AudioHardwareRecordLoop/src/AudioHardwareRecordLoop.c b/audio/test/AudioHardwareRecordLoop/src/AudioHardwareRecordLoop.c
new file mode 100644
index 0000000..9908c0b
--- /dev/null
+++ b/audio/test/AudioHardwareRecordLoop/src/AudioHardwareRecordLoop.c
@@ -0,0 +1,140 @@
+/*---------------------------------------------------------------------------*
+ * AudioHardwareRecord.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include "audioinwrapper.h"
+
+#define SAMPLING_RATE 8000
+
+#define N_FRAMES_PER_BUFFER 512 /* low-level driver counts in terms of frames, not samples */
+#define N_TUPLES_PER_FRAME 1 /* tuple: a set of samples (set of 1 if mono, set of 2 if stereo */
+
+#define N_CHANNELS_PER_TUPLE 1 /* 1: mono; 2: stereo */
+
+#define N_TUPLES_PER_BUFFER (N_FRAMES_PER_BUFFER * N_TUPLES_PER_FRAME)
+#define N_SAMPLES_PER_BUFFER (N_TUPLES_PER_BUFFER * N_CHANNELS_PER_TUPLE)
+
+#define N_RECORDINGS 1000
+#define N_SECONDS_TO_RECORD 5
+#define N_SAMPLES_TO_RECORD (SAMPLING_RATE * N_SECONDS_TO_RECORD * N_CHANNELS_PER_TUPLE)
+
+typedef short typeSample;
+
+/* store incoming samples here, then write to file at the end */
+typeSample recordedSamples[N_SAMPLES_TO_RECORD];
+
+//#define AUDIO_SET_FORMAT_ONCE_ONLY
+
+int main(int argc, char* argv[])
+{
+ int rc;
+ unsigned int iFile;
+
+ const unsigned short delay_ms = 2000; //1800 //340;
+
+ printf("For debugging, this is configured to sleep for %u milliseconds before AudioSetInputFormat(%u)\n\n", delay_ms, SAMPLING_RATE);
+
+#if defined(AUDIO_SET_FORMAT_ONCE_ONLY)
+ rc = AudioSetInputFormat(SAMPLING_RATE, N_CHANNELS_PER_TUPLE);
+ if (rc != 0)
+ {
+ printf("ERROR: AudioSetInputFormat() returns %d\n", rc);
+ exit(1);
+ }
+#endif
+
+ for (iFile = 1; iFile <= N_RECORDINGS; iFile++)
+ {
+ unsigned int i;
+
+#if !defined(AUDIO_SET_FORMAT_ONCE_ONLY)
+ {
+ // see how much of a delay is needed to get rid of error when calling
+ // AudioSetInputFormat() immediately after AudioClose()
+ struct timeval sleep_time_struct;
+ sleep_time_struct.tv_sec = 0;
+ sleep_time_struct.tv_usec = delay_ms*1000; // microseconds
+ select(0, NULL, NULL, NULL, &sleep_time_struct);
+ }
+
+ rc = AudioSetInputFormat(SAMPLING_RATE, N_CHANNELS_PER_TUPLE);
+ if (rc != 0)
+ {
+ printf("ERROR: AudioSetInputFormat() returns %d\n", rc);
+ exit(1);
+ }
+#endif
+
+ printf("Recording: %3d of %3d\n", iFile, N_RECORDINGS);
+
+ memset(recordedSamples, 0, N_SAMPLES_TO_RECORD * sizeof(typeSample));
+
+ rc = AudioOpen();
+ if (rc < 0)
+ {
+ printf("ERROR: AudioOpen() returns %d (device handle/ID)\n", rc);
+ exit(1);
+ }
+
+ i = 0;
+ while (i <= N_SAMPLES_TO_RECORD - N_SAMPLES_PER_BUFFER)
+ {
+ rc = AudioRead(&(recordedSamples[i]), N_FRAMES_PER_BUFFER);
+ if (rc > 0)
+ i += (rc * N_TUPLES_PER_FRAME * N_CHANNELS_PER_TUPLE);
+ else
+ printf("ERROR: AudioRead() returns %d\n", rc);
+ }
+
+ rc = AudioClose();
+ if (rc != 0)
+ {
+ printf("ERROR: AudioClose() returns %d\n", rc);
+ exit(1);
+ }
+
+ /* write to file */
+#if 0
+ {
+ FILE *fpOutput;
+ char szFilename[256];
+
+ sprintf(szFilename, "output_AudioHardwareRecordLoop_%03d.pcm", iFile);
+
+ fpOutput = fopen(szFilename, "wb");
+ if (fpOutput == NULL)
+ {
+ printf("ERROR: cannot create '%s'\n", szFilename);
+ exit(1);
+ }
+ fwrite(recordedSamples, sizeof(typeSample), i, fpOutput);
+ fclose(fpOutput);
+
+ printf("Recording: saved '%s'\n", szFilename);
+ }
+#endif
+ }
+
+ return 0;
+}
diff --git a/audio/test/AudioInRecord/Android.mk b/audio/test/AudioInRecord/Android.mk
new file mode 100644
index 0000000..d8b6ddd
--- /dev/null
+++ b/audio/test/AudioInRecord/Android.mk
@@ -0,0 +1,29 @@
+# Copyright 2006 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# common settings for all ASR builds, exports some variables for sub-makes
+include $(ASR_MAKE_DIR)/Makefile.defs
+
+LOCAL_SRC_FILES:= \
+ src/AudioInRecord.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(ASR_ROOT_DIR)/audio/AudioIn/UNIX/include \
+
+LOCAL_CFLAGS := \
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libhardware \
+ libUAPI_jni \
+
+LOCAL_MODULE:= AudioInRecord
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+
+include $(BUILD_EXECUTABLE)
diff --git a/audio/test/AudioInRecord/src/AudioInRecord.c b/audio/test/AudioInRecord/src/AudioInRecord.c
new file mode 100644
index 0000000..043d09a
--- /dev/null
+++ b/audio/test/AudioInRecord/src/AudioInRecord.c
@@ -0,0 +1,147 @@
+/*---------------------------------------------------------------------------*
+ * AudioInRecord.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#include <mmsystem.h>
+#endif
+#include "audioin.h"
+
+#define SAMPLING_RATE 11025
+
+#define N_FRAMES_PER_BUFFER 512 /* low-level driver counts in terms of frames, not samples */
+#define N_TUPLES_PER_FRAME 1 /* tuple: a set of samples (set of 1 if mono, set of 2 if stereo */
+#define N_CHANNELS_PER_TUPLE 1 /* 1: mono; 2: stereo */
+
+#define N_TUPLES_PER_BUFFER (N_FRAMES_PER_BUFFER * N_TUPLES_PER_FRAME)
+#define N_SAMPLES_PER_BUFFER (N_TUPLES_PER_BUFFER * N_CHANNELS_PER_TUPLE)
+
+#define N_SECONDS_TO_RECORD 10
+#define N_SAMPLES_TO_RECORD (N_SECONDS_TO_RECORD * SAMPLING_RATE * N_CHANNELS_PER_TUPLE)
+
+#define OUTPUT_FILENAME "output_AudioInRecord.pcm"
+
+typedef short typeSample;
+
+/* store incoming samples here, then write to file at the end */
+typeSample recordedSamples[N_SAMPLES_TO_RECORD];
+
+
+int main(int argc, char* argv[])
+{
+ AUDIOIN_H hAudioIn;
+ AUDIOIN_INFO AudioInInfo;
+ LHS_AUDIOIN_ERROR lhsErr;
+ unsigned int nSamples;
+
+ printf("\nAudioTestRecord: capturing %u seconds of audio at %u Hz\n\n", N_SECONDS_TO_RECORD, SAMPLING_RATE);
+
+ memset(recordedSamples, 0, N_SAMPLES_TO_RECORD * sizeof(typeSample));
+
+ printf("Opening the AudioIn device: ");
+ lhsErr = lhs_audioinOpen(WAVE_MAPPER, SAMPLING_RATE, &hAudioIn);
+ printf("lhs_audioinOpen() returns %ld\n", lhsErr);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ printf("ERROR: Unable to open audio device\n\n");
+ return 1;
+ }
+
+ printf("Starting the AudioIn device: ");
+ lhsErr = lhs_audioinStart(hAudioIn);
+ printf("lhs_audioinStart() returns %ld\n", lhsErr);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ printf("ERROR: Unable to start audio device\n\n");
+ printf("Closing the AudioIn device: ");
+ lhsErr = lhs_audioinClose(&hAudioIn);
+ printf("lhs_audioinClose() returns %ld\n", lhsErr);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ printf("ERROR: Unable to close audio device\n\n");
+ return 1;
+ }
+ return 1;
+ }
+
+ printf("... Start Speaking ...\n");
+
+ nSamples = 0;
+ while (nSamples <= N_SAMPLES_TO_RECORD - N_SAMPLES_PER_BUFFER)
+ {
+ unsigned long u32NbrOfSamples;
+
+ u32NbrOfSamples = N_SAMPLES_PER_BUFFER / N_CHANNELS_PER_TUPLE; /* audioin only does mono */
+ lhsErr = lhs_audioinGetSamples(hAudioIn, &u32NbrOfSamples, &(recordedSamples[nSamples]), &AudioInInfo);
+ if (lhsErr == LHS_AUDIOIN_OK)
+ nSamples += u32NbrOfSamples;
+ else
+ printf("ERROR: lhs_audioinGetSamples() returns %ld\n", lhsErr);
+ }
+
+ printf("Stopping the AudioIn device: ");
+ lhsErr = lhs_audioinStop(hAudioIn);
+ printf("lhs_audioinStop() returns %ld\n", lhsErr);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ printf("ERROR: Unable to stop audio device\n\n");
+ printf("Closing the AudioIn device: ");
+ lhsErr = lhs_audioinClose(&hAudioIn);
+ printf("lhs_audioinClose() returns %ld\n", lhsErr);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ printf("ERROR: Unable to close audio device\n\n");
+ return 1;
+ }
+ return 1;
+ }
+
+ printf("Closing the AudioIn device: ");
+ lhsErr = lhs_audioinClose(&hAudioIn);
+ printf("lhs_audioinClose() returns %ld\n", lhsErr);
+ if (lhsErr != LHS_AUDIOIN_OK)
+ {
+ printf("ERROR: Unable to close audio device\n\n");
+ return 1;
+ }
+
+ /* write to file */
+ {
+ FILE *fpOutput;
+ char *szFilename = OUTPUT_FILENAME;
+
+ fpOutput = fopen(szFilename, "wb");
+ if (fpOutput == NULL)
+ {
+ printf("ERROR: cannot create output file: '%s'\n", szFilename);
+ return 1;
+ }
+ fwrite(recordedSamples, sizeof(typeSample), nSamples, fpOutput);
+ fclose(fpOutput);
+
+ printf("\nOutput audio saved to '%s'\n\n", szFilename);
+ }
+
+
+ return 0;
+}