mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-10-25 01:50:30 -04:00
- more obsolete dirs
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/trunk@253 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
fb96e20748
commit
0981dc4123
@ -1,137 +0,0 @@
|
||||
ASIO-README.txt
|
||||
|
||||
This document contains information to help you compile PortAudio with
|
||||
ASIO support. If you find any omissions or errors in this document
|
||||
please notify Ross Bencina <rossb@audiomulch.com>.
|
||||
|
||||
|
||||
Building PortAudio with ASIO support
|
||||
------------------------------------
|
||||
|
||||
To build PortAudio with ASIO support you need to compile and link with
|
||||
pa_asio.c, and files from the ASIO SDK (see below), along with the common
|
||||
files from pa_common/ and platform specific files from pa_win/ (for Win32)
|
||||
or pa_mac/ (for Macintosh).
|
||||
|
||||
If you are compiling with a non-Microsoft compiler on windows, also
|
||||
compile and link with iasiothiscallresolver.cpp (see below for
|
||||
an explanation).
|
||||
|
||||
For some platforms (MingW, possibly Mac), you may simply
|
||||
be able to type:
|
||||
|
||||
./configure --with-host_os=mingw --with-winapi=asio [--with-asiodir=/usr/local/asiosdk2]
|
||||
make
|
||||
|
||||
./configure --with-host_os=darwin --with-winapi=asio [--with-asiodir=/usr/local/asiosdk2]
|
||||
make
|
||||
|
||||
and life will be good.
|
||||
|
||||
|
||||
Obtaining the ASIO SDK
|
||||
----------------------
|
||||
|
||||
In order to build PortAudio with ASIO support, you need to download
|
||||
the ASIO SDK (version 2.0) from Steinberg. Steinberg makes the ASIO
|
||||
SDK available to anyone free of charge, however they do not permit its
|
||||
source code to be distributed.
|
||||
|
||||
NOTE: In some cases the ASIO SDK may require patching, see below
|
||||
for further details.
|
||||
|
||||
http://www.steinberg.net/en/ps/support/3rdparty/asio_sdk/
|
||||
|
||||
If the above link is broken search Google for:
|
||||
"download steinberg ASIO SDK"
|
||||
|
||||
|
||||
|
||||
Building the ASIO SDK on Macintosh
|
||||
----------------------------------
|
||||
|
||||
To build the ASIO SDK on Macintosh you need to compile and link with the
|
||||
following files from the ASIO SDK:
|
||||
|
||||
host/asiodrivers.cpp
|
||||
host/mac/asioshlib.cpp
|
||||
host/mac/codefragements.cpp
|
||||
|
||||
|
||||
|
||||
Building the ASIO SDK on Windows
|
||||
--------------------------------
|
||||
|
||||
To build the ASIO SDK on Windows you need to compile and link with the
|
||||
following files from the ASIO SDK:
|
||||
|
||||
asio_sdk\common\asio.cpp
|
||||
asio_sdk\host\asiodrivers.cpp
|
||||
asio_sdk\host\pc\asiolist.cpp
|
||||
|
||||
You may also need to adjust your include paths to support inclusion of
|
||||
header files from the above directories.
|
||||
|
||||
The ASIO SDK depends on the following COM API functions:
|
||||
CoInitialize, CoUninitialize, CoCreateInstance, CLSIDFromString
|
||||
For compilation with MinGW you will need to link with -lole32, for
|
||||
Borland link with Import32.lib.
|
||||
|
||||
|
||||
|
||||
Non-Microsoft (MSVC) Compilers on Windows including Borland and GCC
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Steinberg did not specify a calling convention in the IASIO interface
|
||||
definition. This causes the Microsoft compiler to use the proprietary
|
||||
thiscall convention which is not compatible with other compilers, such
|
||||
as compilers from Borland (BCC and C++Builder) and GNU (gcc).
|
||||
Steinberg's ASIO SDK will compile but crash on initialization if
|
||||
compiled with a non-Microsoft compiler on Windows.
|
||||
|
||||
PortAudio solves this problem using the iasiothiscallresolver library
|
||||
which is included in the distribution. When building ASIO support for
|
||||
non-Microsoft compilers, be sure to compile and link with
|
||||
iasiothiscallresolver.cpp. Note that iasiothiscallresolver includes
|
||||
conditional directives which cause it to have no effect if it is
|
||||
compiled with a Microsoft compiler, or on the Macintosh.
|
||||
|
||||
If you use configure and make (see above), this should be handled
|
||||
automatically for you.
|
||||
|
||||
For further information about the IASIO thiscall problem see this page:
|
||||
http://www.audiomulch.com/~rossb/code/calliasio
|
||||
|
||||
|
||||
|
||||
Macintosh ASIO SDK Bug Patch
|
||||
----------------------------
|
||||
|
||||
There is a bug in the ASIO SDK that causes the Macintosh version to
|
||||
often fail during initialization. Below is a patch that you can apply.
|
||||
|
||||
In codefragments.cpp replace getFrontProcessDirectory function with
|
||||
the following one (GetFrontProcess replaced by GetCurrentProcess).
|
||||
|
||||
|
||||
bool CodeFragments::getFrontProcessDirectory(void *specs)
|
||||
{
|
||||
FSSpec *fss = (FSSpec *)specs;
|
||||
ProcessInfoRec pif;
|
||||
ProcessSerialNumber psn;
|
||||
|
||||
memset(&psn,0,(long)sizeof(ProcessSerialNumber));
|
||||
// if(GetFrontProcess(&psn) == noErr) // wrong !!!
|
||||
if(GetCurrentProcess(&psn) == noErr) // correct !!!
|
||||
{
|
||||
pif.processName = 0;
|
||||
pif.processAppSpec = fss;
|
||||
pif.processInfoLength = sizeof(ProcessInfoRec);
|
||||
if(GetProcessInformation(&psn, &pif) == noErr)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
---
|
||||
Binary file not shown.
Binary file not shown.
@ -1,563 +0,0 @@
|
||||
/*
|
||||
IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for
|
||||
the top level description - this comment describes the technical details of
|
||||
the implementation.
|
||||
|
||||
The latest version of this file is available from:
|
||||
http://www.audiomulch.com/~rossb/code/calliasio
|
||||
|
||||
please email comments to Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
BACKGROUND
|
||||
|
||||
The IASIO interface declared in the Steinberg ASIO 2 SDK declares
|
||||
functions with no explicit calling convention. This causes MSVC++ to default
|
||||
to using the thiscall convention, which is a proprietary convention not
|
||||
implemented by some non-microsoft compilers - notably borland BCC,
|
||||
C++Builder, and gcc. MSVC++ is the defacto standard compiler used by
|
||||
Steinberg. As a result of this situation, the ASIO sdk will compile with
|
||||
any compiler, however attempting to execute the compiled code will cause a
|
||||
crash due to different default calling conventions on non-Microsoft
|
||||
compilers.
|
||||
|
||||
IASIOThiscallResolver solves the problem by providing an adapter class that
|
||||
delegates to the IASIO interface using the correct calling convention
|
||||
(thiscall). Due to the lack of support for thiscall in the Borland and GCC
|
||||
compilers, the calls have been implemented in assembly language.
|
||||
|
||||
A number of macros are defined for thiscall function calls with different
|
||||
numbers of parameters, with and without return values - it may be possible
|
||||
to modify the format of these macros to make them work with other inline
|
||||
assemblers.
|
||||
|
||||
|
||||
THISCALL DEFINITION
|
||||
|
||||
A number of definitions of the thiscall calling convention are floating
|
||||
around the internet. The following definition has been validated against
|
||||
output from the MSVC++ compiler:
|
||||
|
||||
For non-vararg functions, thiscall works as follows: the object (this)
|
||||
pointer is passed in ECX. All arguments are passed on the stack in
|
||||
right to left order. The return value is placed in EAX. The callee
|
||||
clears the passed arguments from the stack.
|
||||
|
||||
|
||||
FINDING FUNCTION POINTERS FROM AN IASIO POINTER
|
||||
|
||||
The first field of a COM object is a pointer to its vtble. Thus a pointer
|
||||
to an object implementing the IASIO interface also points to a pointer to
|
||||
that object's vtbl. The vtble is a table of function pointers for all of
|
||||
the virtual functions exposed by the implemented interfaces.
|
||||
|
||||
If we consider a variable declared as a pointer to IASO:
|
||||
|
||||
IASIO *theAsioDriver
|
||||
|
||||
theAsioDriver points to:
|
||||
|
||||
object implementing IASIO
|
||||
{
|
||||
IASIOvtbl *vtbl
|
||||
other data
|
||||
}
|
||||
|
||||
in other words, theAsioDriver points to a pointer to an IASIOvtbl
|
||||
|
||||
vtbl points to a table of function pointers:
|
||||
|
||||
IASIOvtbl ( interface IASIO : public IUnknown )
|
||||
{
|
||||
(IUnknown functions)
|
||||
0 virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;
|
||||
4 virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;
|
||||
8 virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;
|
||||
|
||||
(IASIO functions)
|
||||
12 virtual ASIOBool (*init)(void *sysHandle) = 0;
|
||||
16 virtual void (*getDriverName)(char *name) = 0;
|
||||
20 virtual long (*getDriverVersion)() = 0;
|
||||
24 virtual void (*getErrorMessage)(char *string) = 0;
|
||||
28 virtual ASIOError (*start)() = 0;
|
||||
32 virtual ASIOError (*stop)() = 0;
|
||||
36 virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;
|
||||
40 virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;
|
||||
44 virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,
|
||||
long *preferredSize, long *granularity) = 0;
|
||||
48 virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;
|
||||
52 virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;
|
||||
56 virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;
|
||||
60 virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;
|
||||
64 virtual ASIOError (*setClockSource)(long reference) = 0;
|
||||
68 virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
|
||||
72 virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;
|
||||
76 virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,
|
||||
long bufferSize, ASIOCallbacks *callbacks) = 0;
|
||||
80 virtual ASIOError (*disposeBuffers)() = 0;
|
||||
84 virtual ASIOError (*controlPanel)() = 0;
|
||||
88 virtual ASIOError (*future)(long selector,void *opt) = 0;
|
||||
92 virtual ASIOError (*outputReady)() = 0;
|
||||
};
|
||||
|
||||
The numbers in the left column show the byte offset of each function ptr
|
||||
from the beginning of the vtbl. These numbers are used in the code below
|
||||
to select different functions.
|
||||
|
||||
In order to find the address of a particular function, theAsioDriver
|
||||
must first be dereferenced to find the value of the vtbl pointer:
|
||||
|
||||
mov eax, theAsioDriver
|
||||
mov edx, [theAsioDriver] // edx now points to vtbl[0]
|
||||
|
||||
Then an offset must be added to the vtbl pointer to select a
|
||||
particular function, for example vtbl+44 points to the slot containing
|
||||
a pointer to the getBufferSize function.
|
||||
|
||||
Finally vtbl+x must be dereferenced to obtain the value of the function
|
||||
pointer stored in that address:
|
||||
|
||||
call [edx+44] // call the function pointed to by
|
||||
// the value in the getBufferSize field of the vtbl
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
||||
Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same
|
||||
problem by providing a new COM interface which wraps IASIO with an
|
||||
interface that uses portable calling conventions. OpenASIO must be compiled
|
||||
with MSVC, and requires that you ship the OpenASIO DLL with your
|
||||
application.
|
||||
|
||||
|
||||
ACKNOWLEDGEMENTS
|
||||
|
||||
Ross Bencina: worked out the thiscall details above, wrote the original
|
||||
Borland asm macros, and a patch for asio.cpp (which is no longer needed).
|
||||
Thanks to Martin Fay for introducing me to the issues discussed here,
|
||||
and to Rene G. Ceballos for assisting with asm dumps from MSVC++.
|
||||
|
||||
Antti Silvast: converted the original calliasio to work with gcc and NASM
|
||||
by implementing the asm code in a separate file.
|
||||
|
||||
Fraser Adams: modified the original calliasio containing the Borland inline
|
||||
asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax
|
||||
for gcc. This seems a neater approach for gcc than to have a separate .asm
|
||||
file and it means that we only need one version of the thiscall patch.
|
||||
|
||||
Fraser Adams: rewrote the original calliasio patch in the form of the
|
||||
IASIOThiscallResolver class in order to avoid modifications to files from
|
||||
the Steinberg SDK, which may have had potential licence issues.
|
||||
|
||||
Andrew Baldwin: contributed fixes for compatibility problems with more
|
||||
recent versions of the gcc assembler.
|
||||
*/
|
||||
|
||||
|
||||
// We only need IASIOThiscallResolver at all if we are on Win32. For other
|
||||
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
|
||||
// to be safely #include'd whatever the platform to keep client code portable
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
|
||||
|
||||
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
|
||||
// is not used.
|
||||
#if !defined(_MSC_VER)
|
||||
|
||||
|
||||
#include <new>
|
||||
#include <assert.h>
|
||||
|
||||
// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is
|
||||
// #include'd before it in client code, we do NOT want to do this test here.
|
||||
#define iasiothiscallresolver_sourcefile 1
|
||||
#include "iasiothiscallresolver.h"
|
||||
#undef iasiothiscallresolver_sourcefile
|
||||
|
||||
// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want
|
||||
// this macro defined in this translation unit.
|
||||
#undef ASIOInit
|
||||
|
||||
|
||||
// theAsioDriver is a global pointer to the current IASIO instance which the
|
||||
// ASIO SDK uses to perform all actions on the IASIO interface. We substitute
|
||||
// our own forwarding interface into this pointer.
|
||||
extern IASIO* theAsioDriver;
|
||||
|
||||
|
||||
// The following macros define the inline assembler for BORLAND first then gcc
|
||||
|
||||
#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)
|
||||
|
||||
|
||||
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\
|
||||
void *this_ = (thisPtr); \
|
||||
__asm { \
|
||||
mov ecx, this_ ; \
|
||||
mov eax, [ecx] ; \
|
||||
call [eax+funcOffset] ; \
|
||||
mov resultName, eax ; \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\
|
||||
void *this_ = (thisPtr); \
|
||||
__asm { \
|
||||
mov eax, param1 ; \
|
||||
push eax ; \
|
||||
mov ecx, this_ ; \
|
||||
mov eax, [ecx] ; \
|
||||
call [eax+funcOffset] ; \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\
|
||||
void *this_ = (thisPtr); \
|
||||
__asm { \
|
||||
mov eax, param1 ; \
|
||||
push eax ; \
|
||||
mov ecx, this_ ; \
|
||||
mov eax, [ecx] ; \
|
||||
call [eax+funcOffset] ; \
|
||||
mov resultName, eax ; \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\
|
||||
void *this_ = (thisPtr); \
|
||||
void *doubleParamPtr_ (¶m1); \
|
||||
__asm { \
|
||||
mov eax, doubleParamPtr_ ; \
|
||||
push [eax+4] ; \
|
||||
push [eax] ; \
|
||||
mov ecx, this_ ; \
|
||||
mov eax, [ecx] ; \
|
||||
call [eax+funcOffset] ; \
|
||||
mov resultName, eax ; \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\
|
||||
void *this_ = (thisPtr); \
|
||||
__asm { \
|
||||
mov eax, param2 ; \
|
||||
push eax ; \
|
||||
mov eax, param1 ; \
|
||||
push eax ; \
|
||||
mov ecx, this_ ; \
|
||||
mov eax, [ecx] ; \
|
||||
call [eax+funcOffset] ; \
|
||||
mov resultName, eax ; \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
|
||||
void *this_ = (thisPtr); \
|
||||
__asm { \
|
||||
mov eax, param4 ; \
|
||||
push eax ; \
|
||||
mov eax, param3 ; \
|
||||
push eax ; \
|
||||
mov eax, param2 ; \
|
||||
push eax ; \
|
||||
mov eax, param1 ; \
|
||||
push eax ; \
|
||||
mov ecx, this_ ; \
|
||||
mov eax, [ecx] ; \
|
||||
call [eax+funcOffset] ; \
|
||||
mov resultName, eax ; \
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
|
||||
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset ) \
|
||||
__asm__ __volatile__ ("movl (%1), %%edx\n\t" \
|
||||
"call *"#funcOffset"(%%edx)\n\t" \
|
||||
:"=a"(resultName) /* Output Operands */ \
|
||||
:"c"(thisPtr) /* Input Operands */ \
|
||||
); \
|
||||
|
||||
|
||||
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 ) \
|
||||
__asm__ __volatile__ ("pushl %0\n\t" \
|
||||
"movl (%1), %%edx\n\t" \
|
||||
"call *"#funcOffset"(%%edx)\n\t" \
|
||||
: /* Output Operands */ \
|
||||
:"r"(param1), /* Input Operands */ \
|
||||
"c"(thisPtr) \
|
||||
); \
|
||||
|
||||
|
||||
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 ) \
|
||||
__asm__ __volatile__ ("pushl %1\n\t" \
|
||||
"movl (%2), %%edx\n\t" \
|
||||
"call *"#funcOffset"(%%edx)\n\t" \
|
||||
:"=a"(resultName) /* Output Operands */ \
|
||||
:"r"(param1), /* Input Operands */ \
|
||||
"c"(thisPtr) \
|
||||
); \
|
||||
|
||||
|
||||
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 ) \
|
||||
__asm__ __volatile__ ("pushl 4(%1)\n\t" \
|
||||
"pushl (%1)\n\t" \
|
||||
"movl (%2), %%edx\n\t" \
|
||||
"call *"#funcOffset"(%%edx);\n\t" \
|
||||
:"=a"(resultName) /* Output Operands */ \
|
||||
:"a"(¶m1), /* Input Operands */ \
|
||||
/* Note: Using "r" above instead of "a" fails */ \
|
||||
/* when using GCC 3.3.3, and maybe later versions*/\
|
||||
"c"(thisPtr) \
|
||||
); \
|
||||
|
||||
|
||||
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 ) \
|
||||
__asm__ __volatile__ ("pushl %1\n\t" \
|
||||
"pushl %2\n\t" \
|
||||
"movl (%3), %%edx\n\t" \
|
||||
"call *"#funcOffset"(%%edx)\n\t" \
|
||||
:"=a"(resultName) /* Output Operands */ \
|
||||
:"r"(param2), /* Input Operands */ \
|
||||
"r"(param1), \
|
||||
"c"(thisPtr) \
|
||||
); \
|
||||
|
||||
|
||||
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
|
||||
__asm__ __volatile__ ("pushl %1\n\t" \
|
||||
"pushl %2\n\t" \
|
||||
"pushl %3\n\t" \
|
||||
"pushl %4\n\t" \
|
||||
"movl (%5), %%edx\n\t" \
|
||||
"call *"#funcOffset"(%%edx)\n\t" \
|
||||
:"=a"(resultName) /* Output Operands */ \
|
||||
:"r"(param4), /* Input Operands */ \
|
||||
"r"(param3), \
|
||||
"r"(param2), \
|
||||
"r"(param1), \
|
||||
"c"(thisPtr) \
|
||||
); \
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Our static singleton instance.
|
||||
IASIOThiscallResolver IASIOThiscallResolver::instance;
|
||||
|
||||
// Constructor called to initialize static Singleton instance above. Note that
|
||||
// it is important not to clear that_ incase it has already been set by the call
|
||||
// to placement new in ASIOInit().
|
||||
IASIOThiscallResolver::IASIOThiscallResolver()
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor called from ASIOInit() below
|
||||
IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)
|
||||
: that_( that )
|
||||
{
|
||||
}
|
||||
|
||||
// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not
|
||||
// really a COM object, just a wrapper which will work with the ASIO SDK.
|
||||
// If you wanted to use ASIO without the SDK you might want to implement COM
|
||||
// aggregation in these methods.
|
||||
HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)
|
||||
{
|
||||
(void)riid; // suppress unused variable warning
|
||||
|
||||
assert( false ); // this function should never be called by the ASIO SDK.
|
||||
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()
|
||||
{
|
||||
assert( false ); // this function should never be called by the ASIO SDK.
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()
|
||||
{
|
||||
assert( false ); // this function should never be called by the ASIO SDK.
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Implement the IASIO interface methods by performing the vptr manipulation
|
||||
// described above then delegating to the real implementation.
|
||||
ASIOBool IASIOThiscallResolver::init(void *sysHandle)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_1( result, that_, 12, sysHandle );
|
||||
return result;
|
||||
}
|
||||
|
||||
void IASIOThiscallResolver::getDriverName(char *name)
|
||||
{
|
||||
CALL_VOID_THISCALL_1( that_, 16, name );
|
||||
}
|
||||
|
||||
long IASIOThiscallResolver::getDriverVersion()
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_0( result, that_, 20 );
|
||||
return result;
|
||||
}
|
||||
|
||||
void IASIOThiscallResolver::getErrorMessage(char *string)
|
||||
{
|
||||
CALL_VOID_THISCALL_1( that_, 24, string );
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::start()
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_0( result, that_, 28 );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::stop()
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_0( result, that_, 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,
|
||||
long *preferredSize, long *granularity)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_1( result, that_, 52, sampleRate );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_2( result, that_, 60, clocks, numSources );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::setClockSource(long reference)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_1( result, that_, 64, reference );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_2( result, that_, 68, sPos, tStamp );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_1( result, that_, 72, info );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,
|
||||
long numChannels, long bufferSize, ASIOCallbacks *callbacks)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::disposeBuffers()
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_0( result, that_, 80 );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::controlPanel()
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_0( result, that_, 84 );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::future(long selector,void *opt)
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_2( result, that_, 88, selector, opt );
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIOError IASIOThiscallResolver::outputReady()
|
||||
{
|
||||
ASIOBool result;
|
||||
CALL_THISCALL_0( result, that_, 92 );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Implement our substitute ASIOInit() method
|
||||
ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)
|
||||
{
|
||||
// To ensure that our instance's vptr is correctly constructed, even if
|
||||
// ASIOInit is called prior to main(), we explicitly call its constructor
|
||||
// (potentially over the top of an existing instance). Note that this is
|
||||
// pretty ugly, and is only safe because IASIOThiscallResolver has no
|
||||
// destructor and contains no objects with destructors.
|
||||
new((void*)&instance) IASIOThiscallResolver( theAsioDriver );
|
||||
|
||||
// Interpose between ASIO client code and the real driver.
|
||||
theAsioDriver = &instance;
|
||||
|
||||
// Note that we never need to switch theAsioDriver back to point to the
|
||||
// real driver because theAsioDriver is reset to zero in ASIOExit().
|
||||
|
||||
// Delegate to the real ASIOInit
|
||||
return ::ASIOInit(info);
|
||||
}
|
||||
|
||||
|
||||
#endif /* !defined(_MSC_VER) */
|
||||
|
||||
#endif /* Win32 */
|
||||
|
||||
@ -1,197 +0,0 @@
|
||||
// ****************************************************************************
|
||||
// File: IASIOThiscallResolver.h
|
||||
// Description: The IASIOThiscallResolver class implements the IASIO
|
||||
// interface and acts as a proxy to the real IASIO interface by
|
||||
// calling through its vptr table using the thiscall calling
|
||||
// convention. To put it another way, we interpose
|
||||
// IASIOThiscallResolver between ASIO SDK code and the driver.
|
||||
// This is necessary because most non-Microsoft compilers don't
|
||||
// implement the thiscall calling convention used by IASIO.
|
||||
//
|
||||
// iasiothiscallresolver.cpp contains the background of this
|
||||
// problem plus a technical description of the vptr
|
||||
// manipulations.
|
||||
//
|
||||
// In order to use this mechanism one simply has to add
|
||||
// iasiothiscallresolver.cpp to the list of files to compile
|
||||
// and #include <iasiothiscallresolver.h>
|
||||
//
|
||||
// Note that this #include must come after the other ASIO SDK
|
||||
// #includes, for example:
|
||||
//
|
||||
// #include <windows.h>
|
||||
// #include <asiosys.h>
|
||||
// #include <asio.h>
|
||||
// #include <asiodrivers.h>
|
||||
// #include <iasiothiscallresolver.h>
|
||||
//
|
||||
// Actually the important thing is to #include
|
||||
// <iasiothiscallresolver.h> after <asio.h>. We have
|
||||
// incorporated a test to enforce this ordering.
|
||||
//
|
||||
// The code transparently takes care of the interposition by
|
||||
// using macro substitution to intercept calls to ASIOInit()
|
||||
// and ASIOExit(). We save the original ASIO global
|
||||
// "theAsioDriver" in our "that" variable, and then set
|
||||
// "theAsioDriver" to equal our IASIOThiscallResolver instance.
|
||||
//
|
||||
// Whilst this method of resolving the thiscall problem requires
|
||||
// the addition of #include <iasiothiscallresolver.h> to client
|
||||
// code it has the advantage that it does not break the terms
|
||||
// of the ASIO licence by publishing it. We are NOT modifying
|
||||
// any Steinberg code here, we are merely implementing the IASIO
|
||||
// interface in the same way that we would need to do if we
|
||||
// wished to provide an open source ASIO driver.
|
||||
//
|
||||
// For compilation with MinGW -lole32 needs to be added to the
|
||||
// linker options. For BORLAND, linking with Import32.lib is
|
||||
// sufficient.
|
||||
//
|
||||
// The dependencies are with: CoInitialize, CoUninitialize,
|
||||
// CoCreateInstance, CLSIDFromString - used by asiolist.cpp
|
||||
// and are required on Windows whether ThiscallResolver is used
|
||||
// or not.
|
||||
//
|
||||
// Searching for the above strings in the root library path
|
||||
// of your compiler should enable the correct libraries to be
|
||||
// identified if they aren't immediately obvious.
|
||||
//
|
||||
// Note that the current implementation of IASIOThiscallResolver
|
||||
// is not COM compliant - it does not correctly implement the
|
||||
// IUnknown interface. Implementing it is not necessary because
|
||||
// it is not called by parts of the ASIO SDK which call through
|
||||
// theAsioDriver ptr. The IUnknown methods are implemented as
|
||||
// assert(false) to ensure that the code fails if they are
|
||||
// ever called.
|
||||
// Restrictions: None. Public Domain & Open Source distribute freely
|
||||
// You may use IASIOThiscallResolver commercially as well as
|
||||
// privately.
|
||||
// You the user assume the responsibility for the use of the
|
||||
// files, binary or text, and there is no guarantee or warranty,
|
||||
// expressed or implied, including but not limited to the
|
||||
// implied warranties of merchantability and fitness for a
|
||||
// particular purpose. You assume all responsibility and agree
|
||||
// to hold no entity, copyright holder or distributors liable
|
||||
// for any loss of data or inaccurate representations of data
|
||||
// as a result of using IASIOThiscallResolver.
|
||||
// Version: 1.4 Added separate macro CALL_THISCALL_1_DOUBLE from
|
||||
// Andrew Baldwin, and volatile for whole gcc asm blocks,
|
||||
// both for compatibility with newer gcc versions. Cleaned up
|
||||
// Borland asm to use one less register.
|
||||
// 1.3 Switched to including assert.h for better compatibility.
|
||||
// Wrapped entire .h and .cpp contents with a check for
|
||||
// _MSC_VER to provide better compatibility with MS compilers.
|
||||
// Changed Singleton implementation to use static instance
|
||||
// instead of freestore allocated instance. Removed ASIOExit
|
||||
// macro as it is no longer needed.
|
||||
// 1.2 Removed semicolons from ASIOInit and ASIOExit macros to
|
||||
// allow them to be embedded in expressions (if statements).
|
||||
// Cleaned up some comments. Removed combase.c dependency (it
|
||||
// doesn't compile with BCB anyway) by stubbing IUnknown.
|
||||
// 1.1 Incorporated comments from Ross Bencina including things
|
||||
// such as changing name from ThiscallResolver to
|
||||
// IASIOThiscallResolver, tidying up the constructor, fixing
|
||||
// a bug in IASIOThiscallResolver::ASIOExit() and improving
|
||||
// portability through the use of conditional compilation
|
||||
// 1.0 Initial working version.
|
||||
// Created: 6/09/2003
|
||||
// Authors: Fraser Adams
|
||||
// Ross Bencina
|
||||
// Rene G. Ceballos
|
||||
// Martin Fay
|
||||
// Antti Silvast
|
||||
// Andrew Baldwin
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
|
||||
#ifndef included_iasiothiscallresolver_h
|
||||
#define included_iasiothiscallresolver_h
|
||||
|
||||
// We only need IASIOThiscallResolver at all if we are on Win32. For other
|
||||
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
|
||||
// to be safely #include'd whatever the platform to keep client code portable
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
|
||||
|
||||
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
|
||||
// is not used.
|
||||
#if !defined(_MSC_VER)
|
||||
|
||||
|
||||
// The following is in order to ensure that this header is only included after
|
||||
// the other ASIO headers (except for the case of iasiothiscallresolver.cpp).
|
||||
// We need to do this because IASIOThiscallResolver works by eclipsing the
|
||||
// original definition of ASIOInit() with a macro (see below).
|
||||
#if !defined(iasiothiscallresolver_sourcefile)
|
||||
#if !defined(__ASIO_H)
|
||||
#error iasiothiscallresolver.h must be included AFTER asio.h
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <asiodrvr.h> /* From ASIO SDK */
|
||||
|
||||
|
||||
class IASIOThiscallResolver : public IASIO {
|
||||
private:
|
||||
IASIO* that_; // Points to the real IASIO
|
||||
|
||||
static IASIOThiscallResolver instance; // Singleton instance
|
||||
|
||||
// Constructors - declared private so construction is limited to
|
||||
// our Singleton instance
|
||||
IASIOThiscallResolver();
|
||||
IASIOThiscallResolver(IASIO* that);
|
||||
public:
|
||||
|
||||
// Methods from the IUnknown interface. We don't fully implement IUnknown
|
||||
// because the ASIO SDK never calls these methods through theAsioDriver ptr.
|
||||
// These methods are implemented as assert(false).
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||
virtual ULONG STDMETHODCALLTYPE Release();
|
||||
|
||||
// Methods from the IASIO interface, implemented as forwarning calls to that.
|
||||
virtual ASIOBool init(void *sysHandle);
|
||||
virtual void getDriverName(char *name);
|
||||
virtual long getDriverVersion();
|
||||
virtual void getErrorMessage(char *string);
|
||||
virtual ASIOError start();
|
||||
virtual ASIOError stop();
|
||||
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
|
||||
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
|
||||
virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
|
||||
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
|
||||
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
|
||||
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
|
||||
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
|
||||
virtual ASIOError setClockSource(long reference);
|
||||
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
|
||||
virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
|
||||
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks);
|
||||
virtual ASIOError disposeBuffers();
|
||||
virtual ASIOError controlPanel();
|
||||
virtual ASIOError future(long selector,void *opt);
|
||||
virtual ASIOError outputReady();
|
||||
|
||||
// Class method, see ASIOInit() macro below.
|
||||
static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit
|
||||
};
|
||||
|
||||
|
||||
// Replace calls to ASIOInit with our interposing version.
|
||||
// This macro enables us to perform thiscall resolution simply by #including
|
||||
// <iasiothiscallresolver.h> after the asio #includes (this file _must_ be
|
||||
// included _after_ the asio #includes)
|
||||
|
||||
#define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name))
|
||||
|
||||
|
||||
#endif /* !defined(_MSC_VER) */
|
||||
|
||||
#endif /* Win32 */
|
||||
|
||||
#endif /* included_iasiothiscallresolver_h */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,122 +0,0 @@
|
||||
#ifndef PA_ASIO_H
|
||||
#define PA_ASIO_H
|
||||
/*
|
||||
* $Id$
|
||||
* PortAudio Portable Real-Time Audio Library
|
||||
* ASIO specific extensions
|
||||
*
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@brief ASIO-specific PortAudio API extension header file.
|
||||
*/
|
||||
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/** Retrieve legal latency settings for the specificed device, in samples.
|
||||
|
||||
@param device The global index of the device about which the query is being made.
|
||||
@param minLatency A pointer to the location which will recieve the minimum latency value.
|
||||
@param maxLatency A pointer to the location which will recieve the maximum latency value.
|
||||
@param preferredLatency A pointer to the location which will recieve the preferred latency value.
|
||||
@param granularity A pointer to the location which will recieve the granularity. This value
|
||||
determines which values between minLatency and maxLatency are available. ie the step size,
|
||||
if granularity is -1 then available latency settings are powers of two.
|
||||
|
||||
@see ASIOGetBufferSize in the ASIO SDK.
|
||||
|
||||
@todo This function should have a better name, any suggestions?
|
||||
*/
|
||||
PaError PaAsio_GetAvailableLatencyValues( PaDeviceIndex device,
|
||||
long *minLatency, long *maxLatency, long *preferredLatency, long *granularity );
|
||||
|
||||
|
||||
/** Display the ASIO control panel for the specified device.
|
||||
|
||||
@param device The global index of the device whose control panel is to be displayed.
|
||||
@param systemSpecific On Windows, the calling application's main window handle,
|
||||
on Macintosh this value should be zero.
|
||||
*/
|
||||
PaError PaAsio_ShowControlPanel( PaDeviceIndex device, void* systemSpecific );
|
||||
|
||||
|
||||
|
||||
|
||||
/** Retrieve a pointer to a string containing the name of the specified
|
||||
input channel. The string is valid until Pa_Terminate is called.
|
||||
|
||||
The string will be no longer than 32 characters including the null terminator.
|
||||
*/
|
||||
PaError PaAsio_GetInputChannelName( PaDeviceIndex device, int channelIndex,
|
||||
const char** channelName );
|
||||
|
||||
|
||||
/** Retrieve a pointer to a string containing the name of the specified
|
||||
input channel. The string is valid until Pa_Terminate is called.
|
||||
|
||||
The string will be no longer than 32 characters including the null terminator.
|
||||
*/
|
||||
PaError PaAsio_GetOutputChannelName( PaDeviceIndex device, int channelIndex,
|
||||
const char** channelName );
|
||||
|
||||
|
||||
#define paAsioUseChannelSelectors (0x01)
|
||||
|
||||
typedef struct PaAsioStreamInfo{
|
||||
unsigned long size; /**< sizeof(PaAsioStreamInfo) */
|
||||
PaHostApiTypeId hostApiType; /**< paASIO */
|
||||
unsigned long version; /**< 1 */
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
/* Support for opening only specific channels of an ASIO device.
|
||||
If the paAsioUseChannelSelectors flag is set, channelSelectors is a
|
||||
pointer to an array of integers specifying the device channels to use.
|
||||
When used, the length of the channelSelectors array must match the
|
||||
corresponding channelCount parameter to Pa_OpenStream() otherwise a
|
||||
crash may result.
|
||||
The values in the selectors array must specify channels within the
|
||||
range of supported channels for the device or paInvalidChannelCount will
|
||||
result.
|
||||
*/
|
||||
int *channelSelectors;
|
||||
}PaAsioStreamInfo;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PA_ASIO_H */
|
||||
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Portable Audio I/O Library Windows initialization table
|
||||
*
|
||||
* Based on the Open Source API proposed by Ross Bencina
|
||||
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
Mac OS host API initialization function table.
|
||||
*/
|
||||
|
||||
|
||||
#include "pa_hostapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||
PaError PaMacSm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||
PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||
PaError PaMacAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
PaUtilHostApiInitializer *paHostApiInitializers[] =
|
||||
{
|
||||
#ifdef PA_USE_COREAUDIO
|
||||
PaMacCore_Initialize,
|
||||
#endif
|
||||
|
||||
#ifdef PA_USE_SM
|
||||
PaMacSm_Initialize,
|
||||
#endif
|
||||
|
||||
#ifdef PA_USE_JACK
|
||||
PaJack_Initialize,
|
||||
#endif
|
||||
|
||||
#ifdef PA_USE_ASIO
|
||||
PaMacAsio_Initialize,
|
||||
#endif
|
||||
|
||||
PaSkeleton_Initialize, /* just for testing */
|
||||
|
||||
0 /* NULL terminated array */
|
||||
};
|
||||
|
||||
|
||||
int paDefaultHostApiIndex = 0;
|
||||
@ -1,60 +0,0 @@
|
||||
This directory contains various programs to test PortAudio. The files
|
||||
named patest_* are tests, the files named debug_* are just scratch
|
||||
files that may or may not work.
|
||||
|
||||
All following tests are up to date with the V19 API. They should all compile
|
||||
(without any warnings on GCC 3.3). Note that this does not necissarily mean that
|
||||
the tests pass, just that they compile.
|
||||
|
||||
x- paqa_devs.c
|
||||
x- paqa_errs.c (needs reviewing)
|
||||
x- patest1.c
|
||||
x- patest_buffer.c
|
||||
x- patest_callbackstop.c
|
||||
x- patest_clip.c (last test fails, dither doesn't currently force clip in V19)
|
||||
x- patest_dither.c
|
||||
x- patest_hang.c
|
||||
x- patest_latency.c
|
||||
x- patest_leftright.c
|
||||
x- patest_longsine.c
|
||||
x- patest_many.c
|
||||
x- patest_maxsines.c
|
||||
o- patest_mono.c
|
||||
x- patest_multi_sine.c
|
||||
x- patest_pink.c
|
||||
x- patest_prime.c
|
||||
x- patest_read_record.c
|
||||
x- patest_record.c
|
||||
x- patest_ringmix.c
|
||||
x- patest_saw.c
|
||||
x- patest_sine.c
|
||||
x- patest_sine8.c
|
||||
x- patest_sine_formats.c
|
||||
x- patest_sine_time.c
|
||||
x- patest_start_stop.c
|
||||
x- patest_stop.c
|
||||
x- patest_sync.c
|
||||
x- patest_toomanysines.c
|
||||
o- patest_two_rates.c
|
||||
x- patest_underflow.c
|
||||
x- patest_wire.c
|
||||
x- patest_write_sine.c
|
||||
x- pa_devs.c
|
||||
x- pa_fuzz.c
|
||||
x- pa_minlat.c
|
||||
|
||||
The debug_ files are still in V18 format and may need some V19 adaption.
|
||||
Feel free to fix them, most simply require adjusting to the new API.
|
||||
|
||||
o- pa_tests/debug_convert.c
|
||||
o- pa_tests/debug_dither_calc.c
|
||||
o- pa_tests/debug_dual.c
|
||||
o- pa_tests/debug_multi_in.c
|
||||
o- pa_tests/debug_multi_out.c
|
||||
o- pa_tests/debug_record.c
|
||||
o- pa_tests/debug_record_reuse.c
|
||||
o- pa_tests/debug_sine.c
|
||||
o- pa_tests/debug_sine_amp.c
|
||||
o- pa_tests/debug_sine_formats.c
|
||||
o- pa_tests/debug_srate.c
|
||||
o- pa_tests/debug_test1.c
|
||||
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Convert tagged values.
|
||||
*
|
||||
* Author: Phil Burk <philburk@softsynth.com>
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
|
||||
//#define OUTPUT_DEVICE (11)
|
||||
#define NUM_SECONDS (8)
|
||||
#define SLEEP_DUR (800)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
|
||||
#define NUM_BUFFERS (0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int framesToGo;
|
||||
}
|
||||
paTestData;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
short *out = (short*)outputBuffer;
|
||||
int i;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
if( data->framesToGo < framesPerBuffer ) finished = 1;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0x0000 + i; /* left */
|
||||
*out++ = 0x1000 + i; /* right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
int totalSamps;
|
||||
printf("PortAudio Test: output debug values\n" );
|
||||
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
printf("totalSamps = %d\n", totalSamps );
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
printf("PortAudio Test: output device = %d\n", OUTPUT_DEVICE );
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice,
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
2, /* stereo output */
|
||||
paInt16, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
NUM_BUFFERS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff|paDitherOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Is callback being called?\n");
|
||||
for( i=0; i<((NUM_SECONDS+1)*1000); i+=SLEEP_DUR )
|
||||
{
|
||||
printf("data.framesToGo = %d\n", data.framesToGo ); fflush(stdout);
|
||||
Pa_Sleep( SLEEP_DUR );
|
||||
}
|
||||
/* Stop sound until ENTER hit. */
|
||||
printf("Call Pa_StopStream()\n");
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Test Dither calculations.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#include "pa_host.h"
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
long max,min;
|
||||
int i;
|
||||
|
||||
for( i=0; i<10000; i++ )
|
||||
{
|
||||
long dither = PaConvert_TriangularDither();
|
||||
// printf("dither = 0x%08X\n", dither );
|
||||
if( dither < min ) min = dither;
|
||||
else if( dither > max ) max = dither;
|
||||
}
|
||||
printf("min = 0x%08X = %d, max = 0x%08X = %d\n", min, min, max, max );
|
||||
}
|
||||
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_dual.c
|
||||
* Try to open TWO streams on separate cards.
|
||||
* Play a sine sweep using the Portable Audio api for several seconds.
|
||||
* Hacked test for debugging PA.
|
||||
*
|
||||
* Author: Phil Burk <philburk@softsynth.com>
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#define DEV_ID_1 (13)
|
||||
#define DEV_ID_2 (15)
|
||||
#define NUM_SECONDS (8)
|
||||
#define SLEEP_DUR (800)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#if 0
|
||||
#define MIN_LATENCY_MSEC (200)
|
||||
#define NUM_BUFFERS ((MIN_LATENCY_MSEC * SAMPLE_RATE) / (FRAMES_PER_BUFFER * 1000))
|
||||
#else
|
||||
#define NUM_BUFFERS (0)
|
||||
#endif
|
||||
#define MIN_FREQ (100.0f)
|
||||
#define MAX_FREQ (4000.0f)
|
||||
#define FREQ_SCALAR (1.00002f)
|
||||
#define CalcPhaseIncrement(freq) (freq/SAMPLE_RATE)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (400)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE + 1]; // add one for guard point for interpolation
|
||||
float phase_increment;
|
||||
float left_phase;
|
||||
float right_phase;
|
||||
}
|
||||
paTestData;
|
||||
/* Convert phase between and 1.0 to sine value
|
||||
* using linear interpolation.
|
||||
*/
|
||||
float LookupSine( paTestData *data, float phase );
|
||||
float LookupSine( paTestData *data, float phase )
|
||||
{
|
||||
float fIndex = phase*TABLE_SIZE;
|
||||
int index = (int) fIndex;
|
||||
float fract = fIndex - index;
|
||||
float lo = data->sine[index];
|
||||
float hi = data->sine[index+1];
|
||||
float val = lo + fract*(hi-lo);
|
||||
return val;
|
||||
}
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = LookupSine(data, data->left_phase); /* left */
|
||||
*out++ = LookupSine(data, data->right_phase); /* right */
|
||||
data->left_phase += data->phase_increment;
|
||||
if( data->left_phase >= 1.0f ) data->left_phase -= 1.0f;
|
||||
data->right_phase += (data->phase_increment * 1.5f); /* fifth above */
|
||||
if( data->right_phase >= 1.0f ) data->right_phase -= 1.0f;
|
||||
/* sweep frequency then start over. */
|
||||
data->phase_increment *= FREQ_SCALAR;
|
||||
if( data->phase_increment > CalcPhaseIncrement(MAX_FREQ) ) data->phase_increment = CalcPhaseIncrement(MIN_FREQ);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PaError TestStart( PortAudioStream **streamPtr, PaDeviceID devID,
|
||||
paTestData *data );
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PortAudioStream *stream1, *stream2;
|
||||
PaError err;
|
||||
paTestData DATA1, DATA2;
|
||||
printf("PortAudio Test: DUAL sine sweep. ask for %d buffers\n", NUM_BUFFERS );
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
err = TestStart( &stream1, DEV_ID_1, &DATA1 );
|
||||
if( err != paNoError ) goto error;
|
||||
err = TestStart( &stream2, DEV_ID_2, &DATA2 );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Hit ENTER\n");
|
||||
getchar();
|
||||
err = Pa_StopStream( stream1 );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StopStream( stream2 );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
PaError TestStart( PortAudioStream **streamPtr, PaDeviceID devID, paTestData *data )
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
int i;
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data->sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data->sine[TABLE_SIZE] = data->sine[0]; // set guard point
|
||||
data->left_phase = data->right_phase = 0.0;
|
||||
data->phase_increment = CalcPhaseIncrement(MIN_FREQ);
|
||||
printf("PortAudio Test: output device = %d\n", devID );
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice,
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
devID,
|
||||
2, /* stereo output */
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
NUM_BUFFERS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff|paDitherOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
data );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
*streamPtr = stream;
|
||||
return 0;
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_multi_in.c
|
||||
* Pass output from each of multiple channels
|
||||
* to a stereo output using the Portable Audio api.
|
||||
* Hacked test for debugging PA.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "portaudio.h"
|
||||
//#define INPUT_DEVICE_NAME ("EWS88 MT Interleaved Rec")
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
|
||||
//#define OUTPUT_DEVICE (18)
|
||||
#define SAMPLE_RATE (22050)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define MIN_LATENCY_MSEC (400)
|
||||
#define NUM_BUFFERS ((MIN_LATENCY_MSEC * SAMPLE_RATE) / (FRAMES_PER_BUFFER * 1000))
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
int liveChannel;
|
||||
int numChannels;
|
||||
}
|
||||
paTestData;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
float *in = (float*)inputBuffer;
|
||||
int i;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
if( in == NULL ) return 0;
|
||||
for( i=0; i<(int)framesPerBuffer; i++ )
|
||||
{
|
||||
/* Copy one channel of input to output. */
|
||||
*out++ = in[data->liveChannel];
|
||||
*out++ = in[data->liveChannel];
|
||||
in += data->numChannels;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int PaFindDeviceByName( const char *name )
|
||||
{
|
||||
int i;
|
||||
int numDevices;
|
||||
const PaDeviceInfo *pdi;
|
||||
int len = strlen( name );
|
||||
PaDeviceID result = paNoDevice;
|
||||
numDevices = Pa_CountDevices();
|
||||
for( i=0; i<numDevices; i++ )
|
||||
{
|
||||
pdi = Pa_GetDeviceInfo( i );
|
||||
if( strncmp( name, pdi->name, len ) == 0 )
|
||||
{
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
PaDeviceID inputDevice;
|
||||
const PaDeviceInfo *pdi;
|
||||
printf("PortAudio Test: input signal from each channel. %d buffers\n", NUM_BUFFERS );
|
||||
data.liveChannel = 0;
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
#ifdef INPUT_DEVICE_NAME
|
||||
printf("Try to use device: %s\n", INPUT_DEVICE_NAME );
|
||||
inputDevice = PaFindDeviceByName(INPUT_DEVICE_NAME);
|
||||
if( inputDevice == paNoDevice )
|
||||
{
|
||||
printf("Could not find %s. Using default instead.\n", INPUT_DEVICE_NAME );
|
||||
inputDevice = Pa_GetDefaultInputDeviceID();
|
||||
}
|
||||
#else
|
||||
printf("Using default input device.\n");
|
||||
inputDevice = Pa_GetDefaultInputDeviceID();
|
||||
#endif
|
||||
pdi = Pa_GetDeviceInfo( inputDevice );
|
||||
if( pdi == NULL )
|
||||
{
|
||||
printf("Could not get device info!\n");
|
||||
goto error;
|
||||
}
|
||||
data.numChannels = pdi->maxInputChannels;
|
||||
printf("Input Device name is %s\n", pdi->name );
|
||||
printf("Input Device has %d channels.\n", pdi->maxInputChannels);
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
inputDevice,
|
||||
pdi->maxInputChannels,
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
2,
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
NUM_BUFFERS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
data.liveChannel = 0;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
for( i=0; i<data.numChannels; i++ )
|
||||
{
|
||||
data.liveChannel = i;
|
||||
printf("Channel %d being sent to output. Hit ENTER for next channel.", i );
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
}
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_multi_out.c
|
||||
* Play a different sine wave on each channels,
|
||||
* using the Portable Audio api.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define FREQ_INCR (300.0 / SAMPLE_RATE)
|
||||
#define MAX_CHANNELS (64)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numChannels;
|
||||
double phases[MAX_CHANNELS];
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
int frameIndex, channelIndex;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
|
||||
{
|
||||
for( channelIndex=0; channelIndex<data->numChannels; channelIndex++ )
|
||||
{
|
||||
/* Output sine wave on every channel. */
|
||||
*out++ = (float) sin(data->phases[channelIndex]);
|
||||
|
||||
/* Play each channel at a higher frequency. */
|
||||
data->phases[channelIndex] += FREQ_INCR * (4 + channelIndex);
|
||||
if( data->phases[channelIndex] >= (2.0 * M_PI) ) data->phases[channelIndex] -= (2.0 * M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
const PaDeviceInfo *pdi;
|
||||
paTestData data = {0};
|
||||
printf("PortAudio Test: output sine wave on each channel.\n" );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
pdi = Pa_GetDeviceInfo( OUTPUT_DEVICE );
|
||||
data.numChannels = pdi->maxOutputChannels;
|
||||
if( data.numChannels > MAX_CHANNELS ) data.numChannels = MAX_CHANNELS;
|
||||
printf("Number of Channels = %d\n", data.numChannels );
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice, /* default input device */
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
data.numChannels,
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Hit ENTER to stop sound.\n");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_CloseStream( stream );
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,339 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_record.c
|
||||
* Record input into an array.
|
||||
* Save array to a file.
|
||||
* Based on patest_record.c but with various ugly debug hacks thrown in.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "portaudio.h"
|
||||
#define SAMPLE_RATE (22050)
|
||||
#define NUM_SECONDS (10)
|
||||
#define SLEEP_DUR_MSEC (200)
|
||||
#define FRAMES_PER_BUFFER (1<<10)
|
||||
#define NUM_REC_BUFS (0)
|
||||
|
||||
#if 1
|
||||
#define PA_SAMPLE_TYPE paFloat32
|
||||
typedef float SAMPLE;
|
||||
#else
|
||||
#define PA_SAMPLE_TYPE paInt16
|
||||
typedef short SAMPLE;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long frameIndex; /* Index into sample array. */
|
||||
long maxFrameIndex;
|
||||
long samplesPerFrame;
|
||||
long numSamples;
|
||||
SAMPLE *recordedSamples;
|
||||
}
|
||||
paTestData;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int recordCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE *rptr = (SAMPLE*)inputBuffer;
|
||||
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
|
||||
long framesToCalc;
|
||||
unsigned long i;
|
||||
int finished;
|
||||
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
|
||||
|
||||
(void) outputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) outTime;
|
||||
|
||||
if( framesLeft < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = framesLeft;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
finished = 0;
|
||||
}
|
||||
if( inputBuffer == NULL )
|
||||
{
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*wptr++ = 0; /* left */
|
||||
*wptr++ = 0; /* right */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
*wptr++ = *rptr++; /* right */
|
||||
}
|
||||
}
|
||||
data->frameIndex += framesToCalc;
|
||||
return finished;
|
||||
}
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int playCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
|
||||
SAMPLE *wptr = (SAMPLE*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished;
|
||||
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
|
||||
if( outputBuffer == NULL ) return 0;
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) outTime;
|
||||
|
||||
if( framesLeft < framesPerBuffer )
|
||||
{
|
||||
/* final buffer... */
|
||||
for( i=0; i<framesLeft; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
*wptr++ = *rptr++; /* right */
|
||||
}
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*wptr++ = 0; /* left */
|
||||
*wptr++ = 0; /* right */
|
||||
}
|
||||
data->frameIndex += framesLeft;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
*wptr++ = *rptr++; /* right */
|
||||
}
|
||||
data->frameIndex += framesPerBuffer;
|
||||
finished = 0;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
PaError TestRecording( paTestData *dataPtr )
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
int i;
|
||||
|
||||
/* Record some audio. */
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
Pa_GetDefaultInputDeviceID(),
|
||||
dataPtr->samplesPerFrame, /* stereo input */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
paNoDevice,
|
||||
0,
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
NUM_REC_BUFS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
recordCallback,
|
||||
dataPtr );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Now recording!\n"); fflush(stdout);
|
||||
for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
|
||||
{
|
||||
if( Pa_StreamActive( stream ) <= 0)
|
||||
{
|
||||
printf("Stream inactive!\n");
|
||||
break;
|
||||
}
|
||||
if( dataPtr->maxFrameIndex <= dataPtr->frameIndex )
|
||||
{
|
||||
printf("Buffer recording complete.\n");
|
||||
break;
|
||||
}
|
||||
Pa_Sleep(100);
|
||||
printf("index = %d\n", dataPtr->frameIndex ); fflush(stdout);
|
||||
}
|
||||
|
||||
printf("Finished loop. Close stream.\n"); fflush(stdout);
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Done.\n"); fflush(stdout);
|
||||
{
|
||||
SAMPLE max = 0;
|
||||
SAMPLE posVal;
|
||||
int i;
|
||||
for( i=0; i<dataPtr->numSamples; i++ )
|
||||
{
|
||||
posVal = dataPtr->recordedSamples[i];
|
||||
if( posVal < 0 ) posVal = -posVal;
|
||||
if( posVal > max ) max = posVal;
|
||||
}
|
||||
printf("Largest recorded sample = %d\n", max );
|
||||
}
|
||||
/* Write recorded data to a file. */
|
||||
#if 0
|
||||
{
|
||||
FILE *fid;
|
||||
fid = fopen("recorded.raw", "wb");
|
||||
if( fid == NULL )
|
||||
{
|
||||
printf("Could not open file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite( dataPtr->recordedSamples, dataPtr->samplesPerFrame * sizeof(SAMPLE), totalFrames, fid );
|
||||
fclose( fid );
|
||||
printf("Wrote data to 'recorded.raw'\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
PaError TestPlayback( paTestData *dataPtr )
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
int i;
|
||||
|
||||
/* Playback recorded data. */
|
||||
dataPtr->frameIndex = 0;
|
||||
printf("Begin playback.\n"); fflush(stdout);
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice,
|
||||
0, /* NO input */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
Pa_GetDefaultOutputDeviceID(),
|
||||
dataPtr->samplesPerFrame, /* stereo output */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
playCallback,
|
||||
dataPtr );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Waiting for playback to finish.\n"); fflush(stdout);
|
||||
for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
|
||||
{
|
||||
Pa_Sleep(100);
|
||||
printf("index = %d\n", dataPtr->frameIndex );
|
||||
}
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
paTestData data;
|
||||
long totalFrames;
|
||||
long numBytes;
|
||||
long i;
|
||||
printf("patest_record.c\n"); fflush(stdout);
|
||||
|
||||
data.frameIndex = 0;
|
||||
data.samplesPerFrame = 2;
|
||||
data.maxFrameIndex = totalFrames = NUM_SECONDS*SAMPLE_RATE;
|
||||
|
||||
printf("totalFrames = %d\n", totalFrames ); fflush(stdout);
|
||||
data.numSamples = totalFrames * data.samplesPerFrame;
|
||||
|
||||
numBytes = data.numSamples * sizeof(SAMPLE);
|
||||
data.recordedSamples = (SAMPLE *) malloc( numBytes );
|
||||
if( data.recordedSamples == NULL )
|
||||
{
|
||||
printf("Could not allocate record array.\n");
|
||||
exit(1);
|
||||
}
|
||||
for( i=0; i<data.numSamples; i++ ) data.recordedSamples[i] = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
for( i=0; i<2; i++ )
|
||||
{
|
||||
err = TestRecording( &data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = TestPlayback( &data );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
|
||||
free( data.recordedSamples );
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
if( err == paHostError )
|
||||
{
|
||||
fprintf( stderr, "Host Error number: %d\n", Pa_GetHostError() );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1,351 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_record_reuse.c
|
||||
* Record input into an array.
|
||||
* Save array to a file.
|
||||
* Based on patest_record.c but with various ugly debug hacks thrown in.
|
||||
* Loop twice and reuse same streams.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "portaudio.h"
|
||||
#define SAMPLE_RATE (22050)
|
||||
#define NUM_SECONDS (4)
|
||||
#define SLEEP_DUR_MSEC (200)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define NUM_REC_BUFS (0)
|
||||
|
||||
#if 1
|
||||
#define PA_SAMPLE_TYPE paFloat32
|
||||
typedef float SAMPLE;
|
||||
#else
|
||||
#define PA_SAMPLE_TYPE paInt16
|
||||
typedef short SAMPLE;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long frameIndex; /* Index into sample array. */
|
||||
long maxFrameIndex;
|
||||
long samplesPerFrame;
|
||||
long numSamples;
|
||||
PortAudioStream *outputStream;
|
||||
PortAudioStream *inputStream;
|
||||
SAMPLE *recordedSamples;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int recordCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE *rptr = (SAMPLE*)inputBuffer;
|
||||
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
|
||||
long framesToCalc;
|
||||
unsigned long i;
|
||||
int finished;
|
||||
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
|
||||
|
||||
(void) outputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) outTime;
|
||||
|
||||
if( framesLeft < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = framesLeft;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
finished = 0;
|
||||
}
|
||||
if( inputBuffer == NULL )
|
||||
{
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*wptr++ = 0; /* left */
|
||||
*wptr++ = 0; /* right */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
*wptr++ = *rptr++; /* right */
|
||||
}
|
||||
}
|
||||
data->frameIndex += framesToCalc;
|
||||
return finished;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int playCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
|
||||
SAMPLE *wptr = (SAMPLE*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished;
|
||||
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
|
||||
if( outputBuffer == NULL ) return 0;
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) outTime;
|
||||
|
||||
if( framesLeft < framesPerBuffer )
|
||||
{
|
||||
/* final buffer... */
|
||||
for( i=0; i<framesLeft; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
*wptr++ = *rptr++; /* right */
|
||||
}
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*wptr++ = 0; /* left */
|
||||
*wptr++ = 0; /* right */
|
||||
}
|
||||
data->frameIndex += framesLeft;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
*wptr++ = *rptr++; /* right */
|
||||
}
|
||||
data->frameIndex += framesPerBuffer;
|
||||
finished = 0;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
PaError TestRecording( paTestData *dataPtr )
|
||||
{
|
||||
PaError err;
|
||||
int i;
|
||||
int lastIndex = 0;
|
||||
|
||||
/* Open input stream if not already open. */
|
||||
if( dataPtr->inputStream == NULL )
|
||||
{
|
||||
/* Record some audio. */
|
||||
err = Pa_OpenStream(
|
||||
&dataPtr->inputStream,
|
||||
Pa_GetDefaultInputDeviceID(),
|
||||
dataPtr->samplesPerFrame, /* stereo input */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
paNoDevice,
|
||||
0,
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
NUM_REC_BUFS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
recordCallback,
|
||||
dataPtr );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
|
||||
dataPtr->frameIndex = 0;
|
||||
|
||||
err = Pa_StartStream( dataPtr->inputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Now recording!\n"); fflush(stdout);
|
||||
for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
|
||||
{
|
||||
int frameIndex, delta;
|
||||
Pa_Sleep(SLEEP_DUR_MSEC);
|
||||
|
||||
frameIndex = dataPtr->frameIndex;
|
||||
if( Pa_StreamActive( dataPtr->inputStream ) <= 0)
|
||||
{
|
||||
printf("Stream inactive!\n");
|
||||
break;
|
||||
}
|
||||
if( dataPtr->maxFrameIndex <= frameIndex )
|
||||
{
|
||||
printf("Buffer recording complete.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
delta = frameIndex - lastIndex;
|
||||
lastIndex = frameIndex;
|
||||
printf("index = %d, delta = %d\n", frameIndex, delta ); fflush(stdout);
|
||||
}
|
||||
|
||||
err = Pa_StopStream( dataPtr->inputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Done.\n"); fflush(stdout);
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
PaError TestPlayback( paTestData *dataPtr )
|
||||
{
|
||||
PaError err;
|
||||
int i;
|
||||
int lastIndex = 0;
|
||||
|
||||
/* Playback recorded data. */
|
||||
dataPtr->frameIndex = 0;
|
||||
printf("Begin playback.\n"); fflush(stdout);
|
||||
|
||||
/* Open output stream if not already open. */
|
||||
if( dataPtr->outputStream == NULL )
|
||||
{
|
||||
err = Pa_OpenStream(
|
||||
&dataPtr->outputStream,
|
||||
paNoDevice,
|
||||
0, /* NO input */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
Pa_GetDefaultOutputDeviceID(),
|
||||
dataPtr->samplesPerFrame, /* stereo output */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
playCallback,
|
||||
dataPtr );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
|
||||
err = Pa_StartStream( dataPtr->outputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Waiting for playback to finish.\n"); fflush(stdout);
|
||||
for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
|
||||
{
|
||||
int frameIndex, delta;
|
||||
Pa_Sleep(SLEEP_DUR_MSEC);
|
||||
frameIndex = dataPtr->frameIndex;
|
||||
delta = frameIndex - lastIndex;
|
||||
lastIndex = frameIndex;
|
||||
printf("index = %d, delta = %d\n", frameIndex, delta ); fflush(stdout);
|
||||
}
|
||||
|
||||
err = Pa_StopStream( dataPtr->outputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
paTestData data = { 0 };
|
||||
long totalFrames;
|
||||
long numBytes;
|
||||
long i;
|
||||
printf("patest_record.c\n"); fflush(stdout);
|
||||
|
||||
/* Set up test data structure and sample array. */
|
||||
data.frameIndex = 0;
|
||||
data.samplesPerFrame = 2;
|
||||
data.maxFrameIndex = totalFrames = NUM_SECONDS*SAMPLE_RATE;
|
||||
|
||||
printf("totalFrames = %d\n", totalFrames ); fflush(stdout);
|
||||
data.numSamples = totalFrames * data.samplesPerFrame;
|
||||
|
||||
numBytes = data.numSamples * sizeof(SAMPLE);
|
||||
data.recordedSamples = (SAMPLE *) malloc( numBytes );
|
||||
if( data.recordedSamples == NULL )
|
||||
{
|
||||
printf("Could not allocate record array.\n");
|
||||
exit(1);
|
||||
}
|
||||
for( i=0; i<data.numSamples; i++ ) data.recordedSamples[i] = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Record and playback multiple times. */
|
||||
for( i=0; i<2; i++ )
|
||||
{
|
||||
err = TestRecording( &data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = TestPlayback( &data );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
err = Pa_CloseStream( data.inputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( data.outputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
free( data.recordedSamples );
|
||||
Pa_Terminate();
|
||||
|
||||
printf("Test complete.\n"); fflush(stdout);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
if( err == paHostError )
|
||||
{
|
||||
fprintf( stderr, "Host Error number: %d\n", Pa_GetHostError() );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_sine.c
|
||||
* Play a sine sweep using the Portable Audio api for several seconds.
|
||||
* Hacked test for debugging PA.
|
||||
*
|
||||
* Author: Phil Burk <philburk@softsynth.com>
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
|
||||
//#define OUTPUT_DEVICE (11)
|
||||
#define NUM_SECONDS (8)
|
||||
#define SLEEP_DUR (800)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#if 0
|
||||
#define MIN_LATENCY_MSEC (200)
|
||||
#define NUM_BUFFERS ((MIN_LATENCY_MSEC * SAMPLE_RATE) / (FRAMES_PER_BUFFER * 1000))
|
||||
#else
|
||||
#define NUM_BUFFERS (0)
|
||||
#endif
|
||||
#define MIN_FREQ (100.0f)
|
||||
#define MAX_FREQ (4000.0f)
|
||||
#define FREQ_SCALAR (1.00002f)
|
||||
#define CalcPhaseIncrement(freq) (freq/SAMPLE_RATE)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (400)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE + 1]; // add one for guard point for interpolation
|
||||
float phase_increment;
|
||||
float left_phase;
|
||||
float right_phase;
|
||||
unsigned int framesToGo;
|
||||
}
|
||||
paTestData;
|
||||
/* Convert phase between and 1.0 to sine value
|
||||
* using linear interpolation.
|
||||
*/
|
||||
float LookupSine( paTestData *data, float phase );
|
||||
float LookupSine( paTestData *data, float phase )
|
||||
{
|
||||
float fIndex = phase*TABLE_SIZE;
|
||||
int index = (int) fIndex;
|
||||
float fract = fIndex - index;
|
||||
float lo = data->sine[index];
|
||||
float hi = data->sine[index+1];
|
||||
float val = lo + fract*(hi-lo);
|
||||
return val;
|
||||
}
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
int framesToCalc;
|
||||
int i;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
if( data->framesToGo < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = data->framesToGo;
|
||||
data->framesToGo = 0;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
data->framesToGo -= framesPerBuffer;
|
||||
}
|
||||
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*out++ = LookupSine(data, data->left_phase); /* left */
|
||||
*out++ = LookupSine(data, data->right_phase); /* right */
|
||||
data->left_phase += data->phase_increment;
|
||||
if( data->left_phase >= 1.0f ) data->left_phase -= 1.0f;
|
||||
data->right_phase += (data->phase_increment * 1.5f); /* fifth above */
|
||||
if( data->right_phase >= 1.0f ) data->right_phase -= 1.0f;
|
||||
/* sweep frequency then start over. */
|
||||
data->phase_increment *= FREQ_SCALAR;
|
||||
if( data->phase_increment > CalcPhaseIncrement(MAX_FREQ) ) data->phase_increment = CalcPhaseIncrement(MIN_FREQ);
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<(int)framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
int totalSamps;
|
||||
printf("PortAudio Test: output sine sweep. ask for %d buffers\n", NUM_BUFFERS );
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.sine[TABLE_SIZE] = data.sine[0]; // set guard point
|
||||
data.left_phase = data.right_phase = 0.0;
|
||||
data.phase_increment = CalcPhaseIncrement(MIN_FREQ);
|
||||
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
printf("totalSamps = %d\n", totalSamps );
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
printf("PortAudio Test: output device = %d\n", OUTPUT_DEVICE );
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice,
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
2, /* stereo output */
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
NUM_BUFFERS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff|paDitherOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Is callback being called?\n");
|
||||
for( i=0; i<((NUM_SECONDS+1)*1000); i+=SLEEP_DUR )
|
||||
{
|
||||
printf("data.framesToGo = %d\n", data.framesToGo ); fflush(stdout);
|
||||
Pa_Sleep( SLEEP_DUR );
|
||||
}
|
||||
/* Stop sound until ENTER hit. */
|
||||
printf("Call Pa_StopStream()\n");
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Play a different sine wave on each channels,
|
||||
* using the Portable Audio api.
|
||||
* Allos amplitude to be set interactively.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define FREQ_INCR (300.0 / SAMPLE_RATE)
|
||||
#define MAX_CHANNELS (64)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numChannels;
|
||||
double phases[MAX_CHANNELS];
|
||||
float amplitude;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
int frameIndex, channelIndex;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
|
||||
{
|
||||
for( channelIndex=0; channelIndex<data->numChannels; channelIndex++ )
|
||||
{
|
||||
/* Output sine wave on every channel. */
|
||||
*out++ = (float) ( data->amplitude * sin(data->phases[channelIndex]) );
|
||||
|
||||
/* Play each channel at a higher frequency. */
|
||||
data->phases[channelIndex] += FREQ_INCR * (4 + channelIndex);
|
||||
if( data->phases[channelIndex] >= (2.0 * M_PI) ) data->phases[channelIndex] -= (2.0 * M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
char pad[256];
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
const PaDeviceInfo *pdi;
|
||||
paTestData data = {0};
|
||||
printf("PortAudio Test: output sine wave on each channel.\n" );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
pdi = Pa_GetDeviceInfo( OUTPUT_DEVICE );
|
||||
data.numChannels = pdi->maxOutputChannels;
|
||||
if( data.numChannels > MAX_CHANNELS ) data.numChannels = MAX_CHANNELS;
|
||||
printf("Number of Channels = %d\n", data.numChannels );
|
||||
data.amplitude = 1.0;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice, /* default input device */
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
data.numChannels,
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
do
|
||||
{
|
||||
printf("Current amplitude = %f\n", data.amplitude );
|
||||
printf("Enter new amplitude or 'q' to quit.\n");
|
||||
fflush(stdout);
|
||||
gets( pad );
|
||||
if( pad[0] != 'q' )
|
||||
{
|
||||
// I tried to use atof but it seems to be broken on Mac OS X 10.1
|
||||
float amp;
|
||||
sscanf( pad, "%f", & );
|
||||
data.amplitude = amp;
|
||||
}
|
||||
} while( pad[0] != 'q' );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_CloseStream( stream );
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* patest_sine_formats.c
|
||||
* Play a sine wave using the Portable Audio api for several seconds.
|
||||
* Test various data formats.
|
||||
*
|
||||
* Author: Phil Burk
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (10)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
|
||||
#define LEFT_FREQ (SAMPLE_RATE/512.0) /* So we hit 1.0 */
|
||||
#define RIGHT_FREQ (500.0)
|
||||
|
||||
#define AMPLITUDE (1.0)
|
||||
|
||||
/* Select ONE format for testing. */
|
||||
#define TEST_UINT8 (1)
|
||||
#define TEST_INT8 (0)
|
||||
#define TEST_INT16 (0)
|
||||
#define TEST_FLOAT32 (0)
|
||||
|
||||
#if TEST_UINT8
|
||||
#define TEST_FORMAT paUInt8
|
||||
typedef unsigned char SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0x80)
|
||||
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
|
||||
#define FORMAT_NAME "Unsigned 8 Bit"
|
||||
|
||||
#elif TEST_INT8
|
||||
#define TEST_FORMAT paInt8
|
||||
typedef char SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0)
|
||||
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
|
||||
#define FORMAT_NAME "Signed 8 Bit"
|
||||
|
||||
#elif TEST_INT16
|
||||
#define TEST_FORMAT paInt16
|
||||
typedef short SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0)
|
||||
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(32767 * (x)))
|
||||
#define FORMAT_NAME "Signed 16 Bit"
|
||||
|
||||
#elif TEST_FLOAT32
|
||||
#define TEST_FORMAT paFloat32
|
||||
typedef float SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0.0)
|
||||
#define DOUBLE_TO_SAMPLE(x) ((SAMPLE_t)(x))
|
||||
#define FORMAT_NAME "Float 32 Bit"
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double left_phase;
|
||||
double right_phase;
|
||||
unsigned int framesToGo;
|
||||
}
|
||||
paTestData;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE_t *out = (SAMPLE_t *)outputBuffer;
|
||||
SAMPLE_t sample;
|
||||
int i;
|
||||
int framesToCalc;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
if( data->framesToGo < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = data->framesToGo;
|
||||
data->framesToGo = 0;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
data->framesToGo -= framesPerBuffer;
|
||||
}
|
||||
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
data->left_phase += (LEFT_FREQ / SAMPLE_RATE);
|
||||
if( data->left_phase > 1.0) data->left_phase -= 1.0;
|
||||
sample = DOUBLE_TO_SAMPLE( AMPLITUDE * sin( (data->left_phase * M_PI * 2. ))); /**/
|
||||
*out++ = sample;
|
||||
/* *out++ = sample; /**/
|
||||
/* *out++ = 0; /**/
|
||||
|
||||
data->right_phase += (RIGHT_FREQ / SAMPLE_RATE);
|
||||
if( data->right_phase > 1.0) data->right_phase -= 1.0;
|
||||
*out++ = DOUBLE_TO_SAMPLE( AMPLITUDE * sin( (data->right_phase * M_PI * 2. ))); /**/
|
||||
/* *out++ = 0; /* */
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<(int)framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = SAMPLE_ZERO; /* left */
|
||||
*out++ = SAMPLE_ZERO; /* right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PortAudioStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int totalSamps;
|
||||
|
||||
printf("PortAudio Test: output " FORMAT_NAME "\n");
|
||||
|
||||
|
||||
data.left_phase = data.right_phase = 0.0;
|
||||
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
paNoDevice,/* default input device */
|
||||
0, /* no input */
|
||||
TEST_FORMAT,
|
||||
NULL,
|
||||
Pa_GetDefaultOutputDeviceID(), /* default output device */
|
||||
2, /* stereo output */
|
||||
TEST_FORMAT,
|
||||
NULL,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Waiting %d seconds for sound to finish.\n", NUM_SECONDS );
|
||||
while( Pa_StreamActive( stream ) ) Pa_Sleep(10);
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
|
||||
printf("PortAudio Test Finished: " FORMAT_NAME "\n");
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* debug_record_reuse.c
|
||||
* Record input into an array.
|
||||
* Save array to a file.
|
||||
* Based on patest_record.c but with various ugly debug hacks thrown in.
|
||||
* Loop twice and reuse same streams.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define EWS88MT_12_REC (1)
|
||||
#define EWS88MT_12_PLAY (10)
|
||||
#define SBLIVE_REC (2)
|
||||
#define SBLIVE_PLAY (11)
|
||||
|
||||
#if 0
|
||||
#define INPUT_DEVICE_ID Pa_GetDefaultInputDeviceID()
|
||||
#define OUTPUT_DEVICE_ID Pa_GetDefaultOutputDeviceID()
|
||||
#else
|
||||
#define INPUT_DEVICE_ID (EWS88MT_12_REC)
|
||||
#define OUTPUT_DEVICE_ID (SBLIVE_PLAY)
|
||||
#endif
|
||||
|
||||
#define INPUT_SAMPLE_RATE (22050.0)
|
||||
#define OUTPUT_SAMPLE_RATE (22050.0)
|
||||
#define NUM_SECONDS (4)
|
||||
#define SLEEP_DUR_MSEC (1000)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
#define NUM_REC_BUFS (0)
|
||||
#define SAMPLES_PER_FRAME (2)
|
||||
|
||||
#define PA_SAMPLE_TYPE paInt16
|
||||
typedef short SAMPLE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long frameIndex; /* Index into sample array. */
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int recordCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData *) userData;
|
||||
(void) outputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) outTime;
|
||||
|
||||
if( inputBuffer != NULL )
|
||||
{
|
||||
data->frameIndex += framesPerBuffer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int playCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData *) userData;
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) outTime;
|
||||
|
||||
if( outputBuffer != NULL )
|
||||
{
|
||||
data->frameIndex += framesPerBuffer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
PaError MeasureStreamRate( PortAudioStream *stream, paTestData *dataPtr, double *ratePtr )
|
||||
{
|
||||
PaError err;
|
||||
int i;
|
||||
int totalFrames = 0;
|
||||
int totalMSec = 0;
|
||||
|
||||
dataPtr->frameIndex = 0;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ )
|
||||
{
|
||||
int delta, endIndex;
|
||||
|
||||
int startIndex = dataPtr->frameIndex;
|
||||
Pa_Sleep(SLEEP_DUR_MSEC);
|
||||
endIndex = dataPtr->frameIndex;
|
||||
|
||||
delta = endIndex - startIndex;
|
||||
totalFrames += delta;
|
||||
totalMSec += SLEEP_DUR_MSEC;
|
||||
|
||||
printf("index = %d, delta = %d\n", endIndex, delta ); fflush(stdout);
|
||||
}
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
*ratePtr = (totalFrames * 1000.0) / totalMSec;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
void ReportRate( double measuredRate, double expectedRate )
|
||||
{
|
||||
double error;
|
||||
|
||||
error = (measuredRate - expectedRate) / expectedRate;
|
||||
error = (error < 0 ) ? -error : error;
|
||||
|
||||
printf("Measured rate = %6.1f, expected rate = %6.1f\n",
|
||||
measuredRate, expectedRate );
|
||||
if( error > 0.1 )
|
||||
{
|
||||
printf("ERROR: unexpected rate! --------------------- ERROR!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("SUCCESS: rate within tolerance!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
paTestData data = { 0 };
|
||||
long i;
|
||||
double rate;
|
||||
const PaDeviceInfo *pdi;
|
||||
|
||||
PortAudioStream *outputStream;
|
||||
PortAudioStream *inputStream;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
pdi = Pa_GetDeviceInfo( INPUT_DEVICE_ID );
|
||||
printf("Input device = %s\n", pdi->name );
|
||||
pdi = Pa_GetDeviceInfo( OUTPUT_DEVICE_ID );
|
||||
printf("Output device = %s\n", pdi->name );
|
||||
|
||||
/* Open input stream. */
|
||||
err = Pa_OpenStream(
|
||||
&inputStream,
|
||||
INPUT_DEVICE_ID,
|
||||
SAMPLES_PER_FRAME, /* stereo input */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
paNoDevice,
|
||||
0,
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
INPUT_SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
NUM_REC_BUFS, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
recordCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&outputStream,
|
||||
paNoDevice,
|
||||
0, /* NO input */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
OUTPUT_DEVICE_ID,
|
||||
SAMPLES_PER_FRAME, /* stereo output */
|
||||
PA_SAMPLE_TYPE,
|
||||
NULL,
|
||||
OUTPUT_SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
playCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Record and playback multiple times. */
|
||||
for( i=0; i<2; i++ )
|
||||
{
|
||||
printf("Measuring INPUT ------------------------- \n");
|
||||
err = MeasureStreamRate( inputStream, &data, &rate );
|
||||
if( err != paNoError ) goto error;
|
||||
ReportRate( rate, INPUT_SAMPLE_RATE );
|
||||
|
||||
printf("Measuring OUTPUT ------------------------- \n");
|
||||
err = MeasureStreamRate( outputStream, &data, &rate );
|
||||
if( err != paNoError ) goto error;
|
||||
ReportRate( rate, OUTPUT_SAMPLE_RATE );
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
err = Pa_CloseStream( inputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( outputStream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
|
||||
printf("Test complete.\n"); fflush(stdout);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
if( err == paHostError )
|
||||
{
|
||||
fprintf( stderr, "Host Error number: %d\n", Pa_GetHostError() );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
patest1.c
|
||||
Ring modulate the audio input with a 441hz sine wave for 20 seconds
|
||||
using the Portable Audio api
|
||||
Author: Ross Bencina <rossb@audiomulch.com>
|
||||
Modifications:
|
||||
April 5th, 2001 - PLB - Check for NULL inputBuffer.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
float sine[100];
|
||||
int phase;
|
||||
int sampsToGo;
|
||||
}
|
||||
patest1data;
|
||||
static int patest1Callback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long bufferFrames,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
patest1data *data = (patest1data*)userData;
|
||||
float *in = (float*)inputBuffer;
|
||||
float *out = (float*)outputBuffer;
|
||||
int framesToCalc = bufferFrames;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
if(inputBuffer == NULL) return 0;
|
||||
if( data->sampsToGo < bufferFrames )
|
||||
{
|
||||
finished = 1;
|
||||
}
|
||||
for( i=0; i<bufferFrames; i++ )
|
||||
{
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
if( data->phase >= 100 )
|
||||
data->phase = 0;
|
||||
}
|
||||
data->sampsToGo -= bufferFrames;
|
||||
/* zero remainder of final buffer if not already done */
|
||||
for( ; i<bufferFrames; i++ )
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
int main(int argc, char* argv[]);
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
patest1data data;
|
||||
int i;
|
||||
int inputDevice = Pa_GetDefaultInputDeviceID();
|
||||
int outputDevice = Pa_GetDefaultOutputDeviceID();
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<100; i++ )
|
||||
data.sine[i] = sin( ((double)i/100.) * M_PI * 2. );
|
||||
data.phase = 0;
|
||||
data.sampsToGo = 44100 * 4; // 20 seconds
|
||||
/* initialise portaudio subsytem */
|
||||
Pa_Initialize();
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
inputDevice,
|
||||
2, /* stereo input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
outputDevice,
|
||||
2, /* stereo output */
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
44100.,
|
||||
// 22050, /* half second buffers */
|
||||
// 4, /* four buffers */
|
||||
512, /* half second buffers */
|
||||
0, /* four buffers */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patest1Callback,
|
||||
&data );
|
||||
if( err == paNoError )
|
||||
{
|
||||
err = Pa_StartStream( stream );
|
||||
// printf( "Press any key to end.\n" );
|
||||
// getc( stdin ); //wait for input before exiting
|
||||
// Pa_AbortStream( stream );
|
||||
|
||||
printf( "Waiting for stream to complete...\n" );
|
||||
|
||||
while( Pa_StreamActive( stream ) )
|
||||
Pa_Sleep(1000); /* sleep until playback has finished */
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr, "An error occured while opening the portaudio stream\n" );
|
||||
if( err == paHostError )
|
||||
fprintf( stderr, "Host error number: %d\n", Pa_GetHostError() );
|
||||
else
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
}
|
||||
Pa_Terminate();
|
||||
printf( "bye\n" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,230 +0,0 @@
|
||||
/** @file pa_devs.c
|
||||
@brief List available devices, including device information.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
|
||||
@note Define PA_NO_ASIO to compile this code on Windows without
|
||||
ASIO support.
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef PA_NO_ASIO
|
||||
#include "pa_asio.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*******************************************************************/
|
||||
static void PrintSupportedStandardSampleRates(
|
||||
const PaStreamParameters *inputParameters,
|
||||
const PaStreamParameters *outputParameters )
|
||||
{
|
||||
static double standardSampleRates[] = {
|
||||
8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
|
||||
44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */
|
||||
};
|
||||
int i, printCount;
|
||||
PaError err;
|
||||
|
||||
printCount = 0;
|
||||
for( i=0; standardSampleRates[i] > 0; i++ )
|
||||
{
|
||||
err = Pa_IsFormatSupported( inputParameters, outputParameters, standardSampleRates[i] );
|
||||
if( err == paFormatIsSupported )
|
||||
{
|
||||
if( printCount == 0 )
|
||||
{
|
||||
printf( "\t%8.2f", standardSampleRates[i] );
|
||||
printCount = 1;
|
||||
}
|
||||
else if( printCount == 4 )
|
||||
{
|
||||
printf( ",\n\t%8.2f", standardSampleRates[i] );
|
||||
printCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( ", %8.2f", standardSampleRates[i] );
|
||||
++printCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !printCount )
|
||||
printf( "None\n" );
|
||||
else
|
||||
printf( "\n" );
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
int i, numDevices, defaultDisplayed;
|
||||
const PaDeviceInfo *deviceInfo;
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
PaError err;
|
||||
|
||||
|
||||
Pa_Initialize();
|
||||
|
||||
printf( "PortAudio version number = %d\nPortAudio version text = '%s'\n",
|
||||
Pa_GetVersion(), Pa_GetVersionText() );
|
||||
|
||||
|
||||
numDevices = Pa_GetDeviceCount();
|
||||
if( numDevices < 0 )
|
||||
{
|
||||
printf( "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
|
||||
err = numDevices;
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf( "Number of devices = %d\n", numDevices );
|
||||
for( i=0; i<numDevices; i++ )
|
||||
{
|
||||
deviceInfo = Pa_GetDeviceInfo( i );
|
||||
printf( "--------------------------------------- device #%d\n", i );
|
||||
|
||||
/* Mark global and API specific default devices */
|
||||
defaultDisplayed = 0;
|
||||
if( i == Pa_GetDefaultInputDevice() )
|
||||
{
|
||||
printf( "[ Default Input" );
|
||||
defaultDisplayed = 1;
|
||||
}
|
||||
else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultInputDevice )
|
||||
{
|
||||
const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi );
|
||||
printf( "[ Default %s Input", hostInfo->name );
|
||||
defaultDisplayed = 1;
|
||||
}
|
||||
|
||||
if( i == Pa_GetDefaultOutputDevice() )
|
||||
{
|
||||
printf( (defaultDisplayed ? "," : "[") );
|
||||
printf( " Default Output" );
|
||||
defaultDisplayed = 1;
|
||||
}
|
||||
else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultOutputDevice )
|
||||
{
|
||||
const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi );
|
||||
printf( (defaultDisplayed ? "," : "[") );
|
||||
printf( " Default %s Output", hostInfo->name );
|
||||
defaultDisplayed = 1;
|
||||
}
|
||||
|
||||
if( defaultDisplayed )
|
||||
printf( " ]\n" );
|
||||
|
||||
/* print device info fields */
|
||||
printf( "Name = %s\n", deviceInfo->name );
|
||||
printf( "Host API = %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name );
|
||||
printf( "Max inputs = %d", deviceInfo->maxInputChannels );
|
||||
printf( ", Max outputs = %d\n", deviceInfo->maxOutputChannels );
|
||||
|
||||
printf( "Default low input latency = %8.3f\n", deviceInfo->defaultLowInputLatency );
|
||||
printf( "Default low output latency = %8.3f\n", deviceInfo->defaultLowOutputLatency );
|
||||
printf( "Default high input latency = %8.3f\n", deviceInfo->defaultHighInputLatency );
|
||||
printf( "Default high output latency = %8.3f\n", deviceInfo->defaultHighOutputLatency );
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef PA_NO_ASIO
|
||||
/* ASIO specific latency information */
|
||||
if( Pa_GetHostApiInfo( deviceInfo->hostApi )->type == paASIO ){
|
||||
long minLatency, maxLatency, preferredLatency, granularity;
|
||||
|
||||
err = PaAsio_GetAvailableLatencyValues( i,
|
||||
&minLatency, &maxLatency, &preferredLatency, &granularity );
|
||||
|
||||
printf( "ASIO minimum buffer size = %ld\n", minLatency );
|
||||
printf( "ASIO maximum buffer size = %ld\n", maxLatency );
|
||||
printf( "ASIO preferred buffer size = %ld\n", preferredLatency );
|
||||
|
||||
if( granularity == -1 )
|
||||
printf( "ASIO buffer granularity = power of 2\n" );
|
||||
else
|
||||
printf( "ASIO buffer granularity = %ld\n", granularity );
|
||||
}
|
||||
#endif /* !PA_NO_ASIO */
|
||||
#endif /* WIN32 */
|
||||
|
||||
printf( "Default sample rate = %8.2f\n", deviceInfo->defaultSampleRate );
|
||||
|
||||
/* poll for standard sample rates */
|
||||
inputParameters.device = i;
|
||||
inputParameters.channelCount = deviceInfo->maxInputChannels;
|
||||
inputParameters.sampleFormat = paInt16;
|
||||
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
outputParameters.device = i;
|
||||
outputParameters.channelCount = deviceInfo->maxOutputChannels;
|
||||
outputParameters.sampleFormat = paInt16;
|
||||
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
if( inputParameters.channelCount > 0 )
|
||||
{
|
||||
printf("Supported standard sample rates\n for half-duplex 16 bit %d channel input = \n",
|
||||
inputParameters.channelCount );
|
||||
PrintSupportedStandardSampleRates( &inputParameters, NULL );
|
||||
}
|
||||
|
||||
if( outputParameters.channelCount > 0 )
|
||||
{
|
||||
printf("Supported standard sample rates\n for half-duplex 16 bit %d channel output = \n",
|
||||
outputParameters.channelCount );
|
||||
PrintSupportedStandardSampleRates( NULL, &outputParameters );
|
||||
}
|
||||
|
||||
if( inputParameters.channelCount > 0 && outputParameters.channelCount > 0 )
|
||||
{
|
||||
printf("Supported standard sample rates\n for full-duplex 16 bit %d channel input, %d channel output = \n",
|
||||
inputParameters.channelCount, outputParameters.channelCount );
|
||||
PrintSupportedStandardSampleRates( &inputParameters, &outputParameters );
|
||||
}
|
||||
}
|
||||
|
||||
Pa_Terminate();
|
||||
|
||||
printf("----------------------------------------------\n");
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
/** @file pa_fuzz.c
|
||||
@brief Distort input like a fuzz boz.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
/*
|
||||
** Note that many of the older ISA sound cards on PCs do NOT support
|
||||
** full duplex audio (simultaneous record and playback).
|
||||
** And some only support full duplex at lower sample rates.
|
||||
*/
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define PA_SAMPLE_TYPE paFloat32
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
|
||||
typedef float SAMPLE;
|
||||
|
||||
float CubicAmplifier( float input );
|
||||
static int fuzzCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData );
|
||||
|
||||
/* Non-linear amplifier with soft distortion curve. */
|
||||
float CubicAmplifier( float input )
|
||||
{
|
||||
float output, temp;
|
||||
if( input < 0.0 )
|
||||
{
|
||||
temp = input + 1.0f;
|
||||
output = (temp * temp * temp) - 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = input - 1.0f;
|
||||
output = (temp * temp * temp) + 1.0f;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
#define FUZZ(x) CubicAmplifier(CubicAmplifier(CubicAmplifier(CubicAmplifier(x))))
|
||||
|
||||
static int gNumNoInputs = 0;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int fuzzCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
SAMPLE *out = (SAMPLE*)outputBuffer;
|
||||
const SAMPLE *in = (const SAMPLE*)inputBuffer;
|
||||
unsigned int i;
|
||||
(void) timeInfo; /* Prevent unused variable warnings. */
|
||||
(void) statusFlags;
|
||||
(void) userData;
|
||||
|
||||
if( inputBuffer == NULL )
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0; /* left - silent */
|
||||
*out++ = 0; /* right - silent */
|
||||
}
|
||||
gNumNoInputs += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = FUZZ(*in++); /* left - distorted */
|
||||
*out++ = *in++; /* right - clean */
|
||||
}
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
inputParameters.channelCount = 2; /* stereo input */
|
||||
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
0, /* paClipOff, */ /* we won't output out of range samples so don't bother clipping them */
|
||||
fuzzCallback,
|
||||
NULL );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Hit ENTER to stop program.\n");
|
||||
getchar();
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Finished. gNumNoInputs = %d\n", gNumNoInputs );
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return -1;
|
||||
}
|
||||
@ -1,187 +0,0 @@
|
||||
/** @file pa_minlat.c
|
||||
@brief Experiment with different numbers of buffers to determine the
|
||||
minimum latency for a computer.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE (32)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double left_phase;
|
||||
double right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* Very simple synthesis routine to generate two sine waves. */
|
||||
static int paminlatCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned int i;
|
||||
double left_phaseInc = 0.02;
|
||||
double right_phaseInc = 0.06;
|
||||
|
||||
double left_phase = data->left_phase;
|
||||
double right_phase = data->right_phase;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
left_phase += left_phaseInc;
|
||||
if( left_phase > TWOPI ) left_phase -= TWOPI;
|
||||
*out++ = (float) sin( left_phase );
|
||||
|
||||
right_phase += right_phaseInc;
|
||||
if( right_phase > TWOPI ) right_phase -= TWOPI;
|
||||
*out++ = (float) sin( right_phase );
|
||||
}
|
||||
|
||||
data->left_phase = left_phase;
|
||||
data->right_phase = right_phase;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv );
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int go;
|
||||
int outLatency = 0;
|
||||
int minLatency = DEFAULT_BUFFER_SIZE * 2;
|
||||
int framesPerBuffer;
|
||||
double sampleRate = 44100.0;
|
||||
char str[256];
|
||||
|
||||
printf("pa_minlat - Determine minimum latency for your computer.\n");
|
||||
printf(" usage: pa_minlat {userBufferSize}\n");
|
||||
printf(" for example: pa_minlat 64\n");
|
||||
printf("Adjust your stereo until you hear a smooth tone in each speaker.\n");
|
||||
printf("Then try to find the smallest number of frames that still sounds smooth.\n");
|
||||
printf("Note that the sound will stop momentarily when you change the number of buffers.\n");
|
||||
|
||||
/* Get bufferSize from command line. */
|
||||
framesPerBuffer = ( argc > 1 ) ? atol( argv[1] ) : DEFAULT_BUFFER_SIZE;
|
||||
printf("Frames per buffer = %d\n", framesPerBuffer );
|
||||
|
||||
data.left_phase = data.right_phase = 0.0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outLatency = sampleRate * 200.0 / 1000.0; /* 200 msec. */
|
||||
|
||||
/* Try different numBuffers in a loop. */
|
||||
go = 1;
|
||||
while( go )
|
||||
{
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
|
||||
outputParameters.channelCount = 2; /* Stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
|
||||
outputParameters.suggestedLatency = (double)outLatency / sampleRate; /* In seconds. */
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
printf("Latency = %d frames = %6.1f msec.\n", outLatency, outputParameters.suggestedLatency * 1000.0 );
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
sampleRate,
|
||||
framesPerBuffer,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
paminlatCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
if( stream == NULL ) goto error;
|
||||
|
||||
/* Start audio. */
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Ask user for a new nlatency. */
|
||||
printf("\nMove windows around to see if the sound glitches.\n");
|
||||
printf("Latency now %d, enter new number of frames, or 'q' to quit: ", outLatency );
|
||||
fgets( str, 256, stdin );
|
||||
{
|
||||
/* Get rid of newline */
|
||||
size_t l = strlen( str ) - 1;
|
||||
if( str[ l ] == '\n')
|
||||
str[ l ] = '\0';
|
||||
}
|
||||
if( str[0] == 'q' ) go = 0;
|
||||
else
|
||||
{
|
||||
outLatency = atol( str );
|
||||
if( outLatency < minLatency )
|
||||
{
|
||||
printf( "Latency below minimum of %d! Set to minimum!!!\n", minLatency );
|
||||
outLatency = minLatency;
|
||||
}
|
||||
}
|
||||
/* Stop sound until ENTER hit. */
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
printf("A good setting for latency would be somewhat higher than\n");
|
||||
printf("the minimum latency that worked.\n");
|
||||
printf("PortAudio: Test finished.\n");
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return 1;
|
||||
}
|
||||
@ -1,347 +0,0 @@
|
||||
/** @file paqa_devs.c
|
||||
@brief Self Testing Quality Assurance app for PortAudio
|
||||
Try to open each device and run through all the
|
||||
possible configurations.
|
||||
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
|
||||
Pieter adapted to V19 API. Test now relies heavily on
|
||||
Pa_IsFormatSupported(). Uses same 'standard' sample rates
|
||||
as in test pa_devs.c.
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#include "pa_trace.h"
|
||||
|
||||
/****************************************** Definitions ***********/
|
||||
#define MODE_INPUT (0)
|
||||
#define MODE_OUTPUT (1)
|
||||
|
||||
typedef struct PaQaData
|
||||
{
|
||||
unsigned long framesLeft;
|
||||
int numChannels;
|
||||
int bytesPerSample;
|
||||
int mode;
|
||||
short sawPhase;
|
||||
PaSampleFormat format;
|
||||
}
|
||||
PaQaData;
|
||||
|
||||
/****************************************** Prototypes ***********/
|
||||
static void TestDevices( int mode );
|
||||
static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate,
|
||||
int numChannels );
|
||||
static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate,
|
||||
int numChannels, PaSampleFormat format );
|
||||
static int QaCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData );
|
||||
|
||||
/****************************************** Globals ***********/
|
||||
static int gNumPassed = 0;
|
||||
static int gNumFailed = 0;
|
||||
|
||||
/****************************************** Macros ***********/
|
||||
/* Print ERROR if it fails. Tally success or failure. */
|
||||
/* Odd do-while wrapper seems to be needed for some compilers. */
|
||||
#define EXPECT(_exp) \
|
||||
do \
|
||||
{ \
|
||||
if ((_exp)) {\
|
||||
/* printf("SUCCESS for %s\n", #_exp ); */ \
|
||||
gNumPassed++; \
|
||||
} \
|
||||
else { \
|
||||
printf("ERROR - 0x%x - %s for %s\n", result, \
|
||||
((result == 0) ? "-" : Pa_GetErrorText(result)), \
|
||||
#_exp ); \
|
||||
gNumFailed++; \
|
||||
goto error; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/*******************************************************************/
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int QaCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
unsigned long i;
|
||||
short phase;
|
||||
PaQaData *data = (PaQaData *) userData;
|
||||
(void) inputBuffer;
|
||||
|
||||
/* Play simle sawtooth wave. */
|
||||
if( data->mode == MODE_OUTPUT )
|
||||
{
|
||||
phase = data->sawPhase;
|
||||
switch( data->format )
|
||||
{
|
||||
case paFloat32:
|
||||
{
|
||||
float *out = (float *) outputBuffer;
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
phase += 0x123;
|
||||
*out++ = (float) (phase * (1.0 / 32768.0));
|
||||
if( data->numChannels == 2 )
|
||||
{
|
||||
*out++ = (float) (phase * (1.0 / 32768.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case paInt32:
|
||||
{
|
||||
int *out = (int *) outputBuffer;
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
phase += 0x123;
|
||||
*out++ = ((int) phase ) << 16;
|
||||
if( data->numChannels == 2 )
|
||||
{
|
||||
*out++ = ((int) phase ) << 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case paInt16:
|
||||
{
|
||||
short *out = (short *) outputBuffer;
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
phase += 0x123;
|
||||
*out++ = phase;
|
||||
if( data->numChannels == 2 )
|
||||
{
|
||||
*out++ = phase;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
unsigned char *out = (unsigned char *) outputBuffer;
|
||||
unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample;
|
||||
for( i=0; i<numBytes; i++ )
|
||||
{
|
||||
*out++ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
data->sawPhase = phase;
|
||||
}
|
||||
/* Are we through yet? */
|
||||
if( data->framesLeft > framesPerBuffer )
|
||||
{
|
||||
PaUtil_AddTraceMessage("QaCallback: running. framesLeft", data->framesLeft );
|
||||
data->framesLeft -= framesPerBuffer;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PaUtil_AddTraceMessage("QaCallback: DONE! framesLeft", data->framesLeft );
|
||||
data->framesLeft = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError result;
|
||||
EXPECT( ((result=Pa_Initialize()) == 0) );
|
||||
printf("Test OUTPUT ---------------\n");
|
||||
TestDevices( MODE_OUTPUT );
|
||||
printf("Test INPUT ---------------\n");
|
||||
TestDevices( MODE_INPUT );
|
||||
error:
|
||||
Pa_Terminate();
|
||||
printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* Try each output device, through its full range of capabilities. */
|
||||
static void TestDevices( int mode )
|
||||
{
|
||||
int id, jc, i;
|
||||
int maxChannels;
|
||||
const PaDeviceInfo *pdi;
|
||||
static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0,
|
||||
16000.0, 22050.0, 24000.0,
|
||||
32000.0, 44100.0, 48000.0,
|
||||
88200.0, 96000.0,
|
||||
-1.0 }; /* Negative terminated list. */
|
||||
int numDevices = Pa_GetDeviceCount();
|
||||
for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
|
||||
{
|
||||
pdi = Pa_GetDeviceInfo( id );
|
||||
/* Try 1 to maxChannels on each device. */
|
||||
maxChannels = (( mode == MODE_INPUT ) ? pdi->maxInputChannels : pdi->maxOutputChannels);
|
||||
|
||||
for( jc=1; jc<=maxChannels; jc++ )
|
||||
{
|
||||
printf("Name = %s\n", pdi->name );
|
||||
/* Try each standard sample rate. */
|
||||
for( i=0; standardSampleRates[i] > 0; i++ )
|
||||
{
|
||||
TestFormats( mode, (PaDeviceIndex)id, standardSampleRates[i], jc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate,
|
||||
int numChannels )
|
||||
{
|
||||
TestAdvance( mode, deviceID, sampleRate, numChannels, paFloat32 );
|
||||
TestAdvance( mode, deviceID, sampleRate, numChannels, paInt16 );
|
||||
TestAdvance( mode, deviceID, sampleRate, numChannels, paInt32 );
|
||||
/* TestAdvance( mode, deviceID, sampleRate, numChannels, paInt24 ); */
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate,
|
||||
int numChannels, PaSampleFormat format )
|
||||
{
|
||||
PaStreamParameters inputParameters, outputParameters, *ipp, *opp;
|
||||
PaStream *stream = NULL;
|
||||
PaError result = paNoError;
|
||||
PaQaData myData;
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
|
||||
/* Setup data for synthesis thread. */
|
||||
myData.framesLeft = (unsigned long) (sampleRate * 100); /* 100 seconds */
|
||||
myData.numChannels = numChannels;
|
||||
myData.mode = mode;
|
||||
myData.format = format;
|
||||
switch( format )
|
||||
{
|
||||
case paFloat32:
|
||||
case paInt32:
|
||||
case paInt24:
|
||||
myData.bytesPerSample = 4;
|
||||
break;
|
||||
/* case paPackedInt24:
|
||||
myData.bytesPerSample = 3;
|
||||
break; */
|
||||
default:
|
||||
myData.bytesPerSample = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if( mode == MODE_INPUT )
|
||||
{
|
||||
inputParameters.device = deviceID;
|
||||
inputParameters.channelCount = numChannels;
|
||||
inputParameters.sampleFormat = format;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
ipp = &inputParameters;
|
||||
}
|
||||
else
|
||||
ipp = NULL;
|
||||
if( mode == MODE_OUTPUT ) /* Pa_GetDeviceInfo(paNoDevice) COREDUMPS!!! */
|
||||
{
|
||||
outputParameters.device = deviceID;
|
||||
outputParameters.channelCount = numChannels;
|
||||
outputParameters.sampleFormat = format;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
opp = &outputParameters;
|
||||
}
|
||||
else
|
||||
opp = NULL;
|
||||
|
||||
if(paFormatIsSupported == Pa_IsFormatSupported( ipp, opp, sampleRate ))
|
||||
{
|
||||
printf("------ TestAdvance: %s, device = %d, rate = %g, numChannels = %d, format = %lu -------\n",
|
||||
( mode == MODE_INPUT ) ? "INPUT" : "OUTPUT",
|
||||
deviceID, sampleRate, numChannels, (unsigned long)format);
|
||||
EXPECT( ((result = Pa_OpenStream( &stream,
|
||||
ipp,
|
||||
opp,
|
||||
sampleRate,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
QaCallback,
|
||||
&myData ) ) == 0) );
|
||||
if( stream )
|
||||
{
|
||||
PaTime oldStamp, newStamp;
|
||||
unsigned long oldFrames;
|
||||
int minDelay = ( mode == MODE_INPUT ) ? 1000 : 400;
|
||||
/* Was:
|
||||
int minNumBuffers = Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate );
|
||||
int msec = (int) ((minNumBuffers * 3 * 1000.0 * FRAMES_PER_BUFFER) / sampleRate);
|
||||
*/
|
||||
int msec = (int)( 3.0 *
|
||||
(( mode == MODE_INPUT ) ? inputParameters.suggestedLatency : outputParameters.suggestedLatency ));
|
||||
if( msec < minDelay ) msec = minDelay;
|
||||
printf("msec = %d\n", msec); /**/
|
||||
EXPECT( ((result=Pa_StartStream( stream )) == 0) );
|
||||
/* Check to make sure PortAudio is advancing timeStamp. */
|
||||
oldStamp = Pa_GetStreamTime(stream);
|
||||
Pa_Sleep(msec);
|
||||
newStamp = Pa_GetStreamTime(stream);
|
||||
printf("oldStamp = %g,newStamp = %g\n", oldStamp, newStamp ); /**/
|
||||
EXPECT( (oldStamp < newStamp) );
|
||||
/* Check to make sure callback is decrementing framesLeft. */
|
||||
oldFrames = myData.framesLeft;
|
||||
Pa_Sleep(msec);
|
||||
printf("oldFrames = %lu, myData.framesLeft = %lu\n", oldFrames, myData.framesLeft ); /**/
|
||||
EXPECT( (oldFrames > myData.framesLeft) );
|
||||
EXPECT( ((result=Pa_CloseStream( stream )) == 0) );
|
||||
stream = NULL;
|
||||
}
|
||||
}
|
||||
error:
|
||||
if( stream != NULL ) Pa_CloseStream( stream );
|
||||
return result;
|
||||
}
|
||||
@ -1,380 +0,0 @@
|
||||
/** @file paqa_errs.c
|
||||
@brief Self Testing Quality Assurance app for PortAudio
|
||||
Do lots of bad things to test error reporting.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
Pieter Suurmond adapted to V19 API.
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
/*--------- Definitions ---------*/
|
||||
#define MODE_INPUT (0)
|
||||
#define MODE_OUTPUT (1)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
#define SAMPLE_RATE (44100.0)
|
||||
|
||||
typedef struct PaQaData
|
||||
{
|
||||
unsigned long framesLeft;
|
||||
int numChannels;
|
||||
int bytesPerSample;
|
||||
int mode;
|
||||
}
|
||||
PaQaData;
|
||||
|
||||
static int gNumPassed = 0; /* Two globals */
|
||||
static int gNumFailed = 0;
|
||||
|
||||
/*------------------- Macros ------------------------------*/
|
||||
/* Print ERROR if it fails. Tally success or failure. Odd */
|
||||
/* do-while wrapper seems to be needed for some compilers. */
|
||||
|
||||
#define EXPECT(_exp) \
|
||||
do \
|
||||
{ \
|
||||
if ((_exp)) {\
|
||||
gNumPassed++; \
|
||||
} \
|
||||
else { \
|
||||
printf("\nERROR - 0x%x - %s for %s\n", result, Pa_GetErrorText(result), #_exp ); \
|
||||
gNumFailed++; \
|
||||
goto error; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define HOPEFOR(_exp) \
|
||||
do \
|
||||
{ \
|
||||
if ((_exp)) {\
|
||||
gNumPassed++; \
|
||||
} \
|
||||
else { \
|
||||
printf("\nERROR - 0x%x - %s for %s\n", result, Pa_GetErrorText(result), #_exp ); \
|
||||
gNumFailed++; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
It may be called at interrupt level on some machines so don't do anything
|
||||
that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int QaCallback( const void* inputBuffer,
|
||||
void* outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void* userData )
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned char* out = (unsigned char *) outputBuffer;
|
||||
PaQaData* data = (PaQaData *) userData;
|
||||
|
||||
(void)inputBuffer; /* Prevent "unused variable" warnings. */
|
||||
|
||||
/* Zero out buffer so we don't hear terrible noise. */
|
||||
if( data->mode == MODE_OUTPUT )
|
||||
{
|
||||
unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample;
|
||||
for( i=0; i<numBytes; i++ )
|
||||
{
|
||||
*out++ = 0;
|
||||
}
|
||||
}
|
||||
/* Are we through yet? */
|
||||
if( data->framesLeft > framesPerBuffer )
|
||||
{
|
||||
data->framesLeft -= framesPerBuffer;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->framesLeft = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static PaDeviceIndex FindInputOnlyDevice(void)
|
||||
{
|
||||
PaDeviceIndex result = Pa_GetDefaultInputDevice();
|
||||
if( result != paNoDevice && Pa_GetDeviceInfo(result)->maxOutputChannels == 0 )
|
||||
return result;
|
||||
|
||||
for( result = 0; result < Pa_GetDeviceCount(); ++result )
|
||||
{
|
||||
if( Pa_GetDeviceInfo(result)->maxOutputChannels == 0 )
|
||||
return result;
|
||||
}
|
||||
|
||||
return paNoDevice;
|
||||
}
|
||||
|
||||
static PaDeviceIndex FindOutputOnlyDevice(void)
|
||||
{
|
||||
PaDeviceIndex result = Pa_GetDefaultOutputDevice();
|
||||
if( result != paNoDevice && Pa_GetDeviceInfo(result)->maxInputChannels == 0 )
|
||||
return result;
|
||||
|
||||
for( result = 0; result < Pa_GetDeviceCount(); ++result )
|
||||
{
|
||||
if( Pa_GetDeviceInfo(result)->maxInputChannels == 0 )
|
||||
return result;
|
||||
}
|
||||
|
||||
return paNoDevice;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------*/
|
||||
static int TestBadOpens( void )
|
||||
{
|
||||
PaStream* stream = NULL;
|
||||
PaError result;
|
||||
PaQaData myData;
|
||||
PaStreamParameters ipp, opp;
|
||||
|
||||
/* Setup data for synthesis thread. */
|
||||
myData.framesLeft = (unsigned long) (SAMPLE_RATE * 100); /* 100 seconds */
|
||||
myData.numChannels = 1;
|
||||
myData.mode = MODE_OUTPUT;
|
||||
|
||||
/*----------------------------- No devices specified: */
|
||||
ipp.device = opp.device = paNoDevice;
|
||||
ipp.channelCount = opp.channelCount = 0; /* Also no channels. */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
/* Take the low latency of the default device for all subsequent tests. */
|
||||
ipp.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultLowInputLatency;
|
||||
opp.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice())->defaultLowOutputLatency;
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidDevice));
|
||||
|
||||
/*----------------------------- No devices specified #2: */
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, NULL,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidDevice));
|
||||
|
||||
/*----------------------------- Out of range input device specified: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = Pa_GetDeviceCount(); /* And no output device, and no channels. */
|
||||
opp.channelCount = 0; opp.device = paNoDevice;
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidDevice));
|
||||
|
||||
/*----------------------------- Out of range output device specified: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no channels. */
|
||||
opp.channelCount = 0; opp.device = Pa_GetDeviceCount();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidDevice));
|
||||
|
||||
/*----------------------------- Zero input channels: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = Pa_GetDefaultInputDevice();
|
||||
opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no output channels. */
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
|
||||
|
||||
/*----------------------------- Zero output channels: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no input channels. */
|
||||
opp.channelCount = 0; opp.device = Pa_GetDefaultOutputDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
|
||||
|
||||
/*----------------------------- Nonzero input and output channels but no output device: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 2; ipp.device = Pa_GetDefaultInputDevice(); /* Both stereo. */
|
||||
opp.channelCount = 2; opp.device = paNoDevice;
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidDevice));
|
||||
|
||||
/*----------------------------- Nonzero input and output channels but no input device: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 2; ipp.device = paNoDevice;
|
||||
opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidDevice));
|
||||
|
||||
/*----------------------------- NULL stream pointer: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice; /* Output is more likely than input. */
|
||||
opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); /* Only 2 output channels. */
|
||||
HOPEFOR(((result = Pa_OpenStream(NULL, &ipp, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paBadStreamPtr));
|
||||
|
||||
/*----------------------------- Low sample rate: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice;
|
||||
opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
1.0, FRAMES_PER_BUFFER, /* 1 cycle per second (1 Hz) is too low. */
|
||||
paClipOff, QaCallback, &myData )) == paInvalidSampleRate));
|
||||
|
||||
/*----------------------------- High sample rate: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice;
|
||||
opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
10000000.0, FRAMES_PER_BUFFER, /* 10^6 cycles per second (10 MHz) is too high. */
|
||||
paClipOff, QaCallback, &myData )) == paInvalidSampleRate));
|
||||
|
||||
/*----------------------------- NULL callback: */
|
||||
/* NULL callback is valid in V19 -- it means use blocking read/write stream
|
||||
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice;
|
||||
opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff,
|
||||
NULL,
|
||||
&myData )) == paNullCallback));
|
||||
*/
|
||||
|
||||
/*----------------------------- Bad flag: */
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice;
|
||||
opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
255, /* Is 8 maybe legal V19 API? */
|
||||
QaCallback, &myData )) == paInvalidFlag));
|
||||
|
||||
/*----------------------------- using input device as output device: */
|
||||
if( FindInputOnlyDevice() != paNoDevice )
|
||||
{
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no channels. */
|
||||
opp.channelCount = 2; opp.device = FindInputOnlyDevice();
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
|
||||
}
|
||||
|
||||
/*----------------------------- using output device as input device: */
|
||||
if( FindOutputOnlyDevice() != paNoDevice )
|
||||
{
|
||||
ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
|
||||
ipp.sampleFormat = opp.sampleFormat = paFloat32;
|
||||
ipp.channelCount = 2; ipp.device = FindOutputOnlyDevice();
|
||||
opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no channels. */
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL,
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
|
||||
|
||||
}
|
||||
|
||||
if( stream != NULL ) Pa_CloseStream( stream );
|
||||
return result;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------------*/
|
||||
static int TestBadActions( void )
|
||||
{
|
||||
PaStream* stream = NULL;
|
||||
PaError result;
|
||||
PaQaData myData;
|
||||
PaStreamParameters opp;
|
||||
|
||||
/* Setup data for synthesis thread. */
|
||||
myData.framesLeft = (unsigned long)(SAMPLE_RATE * 100); /* 100 seconds */
|
||||
myData.numChannels = 1;
|
||||
myData.mode = MODE_OUTPUT;
|
||||
|
||||
opp.device = Pa_GetDefaultOutputDevice(); /* Default output. */
|
||||
opp.channelCount = 2; /* Stereo output. */
|
||||
opp.hostApiSpecificStreamInfo = NULL;
|
||||
opp.sampleFormat = paFloat32;
|
||||
opp.suggestedLatency = Pa_GetDeviceInfo(opp.device)->defaultLowOutputLatency;
|
||||
|
||||
HOPEFOR(((result = Pa_OpenStream(&stream, NULL, /* Take NULL as input parame- */
|
||||
&opp, /* ters, meaning try only output. */
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER,
|
||||
paClipOff, QaCallback, &myData )) == paNoError));
|
||||
|
||||
HOPEFOR(((result = Pa_StartStream(NULL)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = Pa_StopStream(NULL)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = Pa_IsStreamStopped(NULL)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = Pa_IsStreamActive(NULL)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = Pa_CloseStream(NULL)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = Pa_SetStreamFinishedCallback(NULL, NULL)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = !Pa_GetStreamInfo(NULL))));
|
||||
HOPEFOR(((result = Pa_GetStreamTime(NULL)) == 0.0));
|
||||
HOPEFOR(((result = Pa_GetStreamCpuLoad(NULL)) == 0.0));
|
||||
HOPEFOR(((result = Pa_ReadStream(NULL, NULL, 0)) == paBadStreamPtr));
|
||||
HOPEFOR(((result = Pa_WriteStream(NULL, NULL, 0)) == paBadStreamPtr));
|
||||
|
||||
/** @todo test Pa_GetStreamReadAvailable and Pa_GetStreamWriteAvailable */
|
||||
|
||||
if (stream != NULL) Pa_CloseStream(stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError result;
|
||||
|
||||
EXPECT(((result = Pa_Initialize()) == paNoError));
|
||||
TestBadOpens();
|
||||
TestBadActions();
|
||||
error:
|
||||
Pa_Terminate();
|
||||
printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed);
|
||||
return 0;
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
/** @file patest1.c
|
||||
@brief Ring modulate the audio input with a sine wave for 20 seconds.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RATE (44100)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float sine[100];
|
||||
int phase;
|
||||
int sampsToGo;
|
||||
}
|
||||
patest1data;
|
||||
|
||||
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
patest1data *data = (patest1data*)userData;
|
||||
float *in = (float*)inputBuffer;
|
||||
float *out = (float*)outputBuffer;
|
||||
int framesToCalc = framesPerBuffer;
|
||||
unsigned long i = 0;
|
||||
int finished;
|
||||
|
||||
if( data->sampsToGo < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = data->sampsToGo;
|
||||
finished = paComplete;
|
||||
}
|
||||
else
|
||||
{
|
||||
finished = paContinue;
|
||||
}
|
||||
|
||||
for( ; i<framesToCalc; i++ )
|
||||
{
|
||||
*out++ = *in++ * data->sine[data->phase]; /* left */
|
||||
*out++ = *in++ * data->sine[data->phase++]; /* right */
|
||||
if( data->phase >= 100 )
|
||||
data->phase = 0;
|
||||
}
|
||||
|
||||
data->sampsToGo -= framesToCalc;
|
||||
|
||||
/* zero remainder of final buffer if not already done */
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]);
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
patest1data data;
|
||||
int i;
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
const PaHostErrorInfo* herr;
|
||||
|
||||
printf("patest1.c\n"); fflush(stdout);
|
||||
printf("Ring modulate input for 20 seconds.\n"); fflush(stdout);
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<100; i++ )
|
||||
data.sine[i] = sin( ((double)i/100.) * M_PI * 2. );
|
||||
data.phase = 0;
|
||||
data.sampsToGo = SAMPLE_RATE * 20; /* 20 seconds. */
|
||||
|
||||
/* initialise portaudio subsytem */
|
||||
err = Pa_Initialize();
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
inputParameters.channelCount = 2; /* stereo input */
|
||||
inputParameters.sampleFormat = paFloat32; /* 32 bit floating point input */
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
&outputParameters,
|
||||
(double)SAMPLE_RATE, /* Samplerate in Hertz. */
|
||||
512, /* Small buffers */
|
||||
paClipOff, /* We won't output out of range samples so don't bother clipping them. */
|
||||
patest1Callback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
printf( "Press any key to end.\n" ); fflush(stdout);
|
||||
|
||||
getc( stdin ); /* wait for input before exiting */
|
||||
|
||||
err = Pa_AbortStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
printf( "Waiting for stream to complete...\n" );
|
||||
|
||||
/* sleep until playback has finished */
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(1000);
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
|
||||
if( err != paNoError )
|
||||
{
|
||||
fprintf( stderr, "An error occured while using portaudio\n" );
|
||||
if( err == paUnanticipatedHostError )
|
||||
{
|
||||
fprintf( stderr, " unanticipated host error.\n");
|
||||
herr = Pa_GetLastHostErrorInfo();
|
||||
if (herr)
|
||||
{
|
||||
fprintf( stderr, " Error number: %ld\n", herr->errorCode );
|
||||
if (herr->errorText)
|
||||
fprintf( stderr, " Error text: %s\n", herr->errorText );
|
||||
}
|
||||
else
|
||||
fprintf( stderr, " Pa_GetLastHostErrorInfo() failed!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr, " Error number: %d\n", err );
|
||||
fprintf( stderr, " Error text: %s\n", Pa_GetErrorText( err ) );
|
||||
}
|
||||
|
||||
err = 1; /* Always return 0 or 1, but no other return codes. */
|
||||
}
|
||||
|
||||
printf( "bye\n" );
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -1,180 +0,0 @@
|
||||
/** @file patest_buffer.c
|
||||
@brief Test opening streams with different buffer sizes.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#define NUM_SECONDS (1)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (200)
|
||||
|
||||
#define BUFFER_TABLE 9
|
||||
long buffer_table[] = {200,256,500,512,600, 723, 1000, 1024, 2345};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
unsigned int sampsToGo;
|
||||
}
|
||||
paTestData;
|
||||
PaError TestOnce( int buffersize );
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
short *out = (short*)outputBuffer;
|
||||
unsigned int i;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent "unused variable" warnings. */
|
||||
|
||||
if( data->sampsToGo < framesPerBuffer )
|
||||
{
|
||||
/* final buffer... */
|
||||
|
||||
for( i=0; i<data->sampsToGo; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
data->sampsToGo -= framesPerBuffer;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
PaError err;
|
||||
printf("Test opening streams with different buffer sizes\n\n");
|
||||
|
||||
for (i = 0 ; i < BUFFER_TABLE; i++)
|
||||
{
|
||||
printf("Buffer size %ld\n", buffer_table[i]);
|
||||
err = TestOnce(buffer_table[i]);
|
||||
if( err < 0 ) return 0;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PaError TestOnce( int buffersize )
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
int totalSamps;
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (short) (32767.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
|
||||
}
|
||||
data.left_phase = data.right_phase = 0;
|
||||
data.sampsToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paInt16; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
buffersize, /* frames per buffer */
|
||||
(paClipOff | paDitherOff),
|
||||
patest1Callback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Waiting for sound to finish.\n");
|
||||
Pa_Sleep(1000);
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
return paNoError;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,221 +0,0 @@
|
||||
/** @file patest_callbackstop.c
|
||||
@brief Test the paComplete callback result code.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (5)
|
||||
#define NUM_LOOPS (4)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (67)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int phase;
|
||||
unsigned long generatedFramesCount;
|
||||
volatile int callbackReturnedPaComplete;
|
||||
volatile int callbackInvokedAfterReturningPaComplete;
|
||||
}
|
||||
TestData;
|
||||
|
||||
/*
|
||||
This routine will be called by the PortAudio stream when audio is needed.
|
||||
It may be called at interrupt level on some machines so don't do anything
|
||||
that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int TestCallback( const void *input, void *output,
|
||||
unsigned long frameCount,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
TestData *data = (TestData*)userData;
|
||||
float *out = (float*)output;
|
||||
unsigned long i;
|
||||
float x;
|
||||
|
||||
(void) input; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
|
||||
if( data->callbackReturnedPaComplete )
|
||||
data->callbackInvokedAfterReturningPaComplete = 1;
|
||||
|
||||
for( i=0; i<frameCount; i++ )
|
||||
{
|
||||
/* generate tone */
|
||||
|
||||
x = data->sine[ data->phase++ ];
|
||||
if( data->phase >= TABLE_SIZE )
|
||||
data->phase -= TABLE_SIZE;
|
||||
|
||||
*out++ = x; /* left */
|
||||
*out++ = x; /* right */
|
||||
}
|
||||
|
||||
data->generatedFramesCount += frameCount;
|
||||
if( data->generatedFramesCount >= (NUM_SECONDS * SAMPLE_RATE) )
|
||||
{
|
||||
data->callbackReturnedPaComplete = 1;
|
||||
return paComplete;
|
||||
}
|
||||
else
|
||||
{
|
||||
return paContinue;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
TestData data;
|
||||
int i, j;
|
||||
|
||||
|
||||
printf( "PortAudio Test: output sine wave. SR = %d, BufSize = %d\n",
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER );
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice();
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* output will be in-range, so no need to clip */
|
||||
TestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Repeating test %d times.\n", NUM_LOOPS );
|
||||
|
||||
for( i=0; i < NUM_LOOPS; ++i )
|
||||
{
|
||||
data.phase = 0;
|
||||
data.generatedFramesCount = 0;
|
||||
data.callbackReturnedPaComplete = 0;
|
||||
data.callbackInvokedAfterReturningPaComplete = 0;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS );
|
||||
|
||||
/* wait for the callback to complete generating NUM_SECONDS of tone */
|
||||
|
||||
do
|
||||
{
|
||||
Pa_Sleep( 500 );
|
||||
}
|
||||
while( !data.callbackReturnedPaComplete );
|
||||
|
||||
printf( "Callback returned paComplete.\n" );
|
||||
printf( "Waiting for buffers to finish playing...\n" );
|
||||
|
||||
/* wait for stream to become inactive,
|
||||
or for a timeout of approximately NUM_SECONDS
|
||||
*/
|
||||
|
||||
j = 0;
|
||||
while( (err = Pa_IsStreamActive( stream )) == 1 && j < NUM_SECONDS * 2 )
|
||||
{
|
||||
printf(".\n" );
|
||||
Pa_Sleep( 500 );
|
||||
++j;
|
||||
}
|
||||
|
||||
if( err < 0 )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
else if( err == 1 )
|
||||
{
|
||||
printf( "TEST FAILED: Timed out waiting for buffers to finish playing.\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Buffers finished.\n" );
|
||||
}
|
||||
|
||||
if( data.callbackInvokedAfterReturningPaComplete )
|
||||
{
|
||||
printf( "TEST FAILED: Callback was invoked after returning paComplete.\n" );
|
||||
}
|
||||
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,178 +0,0 @@
|
||||
/** @file patest_clip.c
|
||||
@brief Play a sine wave for several seconds at an amplitude
|
||||
that would require clipping.
|
||||
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (4)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (200)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
float amplitude;
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
PaError PlaySine( paTestData *data, unsigned long flags, float amplitude );
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int sineCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
float amplitude = data->amplitude;
|
||||
unsigned int i;
|
||||
(void) inputBuffer; /* Prevent "unused variable" warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = amplitude * data->sine[data->left_phase]; /* left */
|
||||
*out++ = amplitude * data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
|
||||
printf("PortAudio Test: output sine wave with and without clipping.\n");
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
|
||||
printf("\nHalf amplitude. Should sound like sine wave.\n"); fflush(stdout);
|
||||
err = PlaySine( &data, paClipOff | paDitherOff, 0.5f );
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
printf("\nFull amplitude. Should sound like sine wave.\n"); fflush(stdout);
|
||||
err = PlaySine( &data, paClipOff | paDitherOff, 0.999f );
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
printf("\nOver range with clipping and dithering turned OFF. Should sound very nasty.\n");
|
||||
fflush(stdout);
|
||||
err = PlaySine( &data, paClipOff | paDitherOff, 1.1f );
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
printf("\nOver range with clipping and dithering turned ON. Should sound smoother than previous.\n");
|
||||
fflush(stdout);
|
||||
err = PlaySine( &data, paNoFlag, 1.1f );
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
printf("\nOver range with paClipOff but dithering ON.\n"
|
||||
"That forces clipping ON so it should sound the same as previous.\n");
|
||||
fflush(stdout);
|
||||
err = PlaySine( &data, paClipOff, 1.1f );
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return 1;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
PaError PlaySine( paTestData *data, unsigned long flags, float amplitude )
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
|
||||
data->left_phase = data->right_phase = 0;
|
||||
data->amplitude = amplitude;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
1024,
|
||||
flags,
|
||||
sineCallback,
|
||||
data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Sleep( NUM_SECONDS * 1000 );
|
||||
printf("CPULoad = %8.6f\n", Pa_GetStreamCpuLoad( stream ) );
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
return paNoError;
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
@ -1,178 +0,0 @@
|
||||
/** @file patest_dither.c
|
||||
@brief Attempt to hear difference between dithered and non-dithered signal.
|
||||
|
||||
This only has an effect if the native format is 16 bit.
|
||||
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (5)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (200)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
float amplitude;
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int sineCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo *timeInfo,
|
||||
PaStreamCallbackFlags statusFlags, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
float amplitude = data->amplitude;
|
||||
unsigned int i;
|
||||
(void) inputBuffer;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = amplitude * data->sine[data->left_phase]; /* left */
|
||||
*out++ = amplitude * data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
V18 version did not call Pa_Terminate() if Pa_Initialize() failed.
|
||||
This V19 version ALWAYS calls Pa_Terminate(). PS.
|
||||
*/
|
||||
PaError PlaySine( paTestData *data, PaStreamFlags flags, float amplitude );
|
||||
PaError PlaySine( paTestData *data, PaStreamFlags flags, float amplitude )
|
||||
{
|
||||
PaStream* stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
|
||||
data->left_phase = data->right_phase = 0;
|
||||
data->amplitude = amplitude;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if (err != paNoError)
|
||||
goto done;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
|
||||
/* When you change this, also */
|
||||
/* adapt the callback routine! */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )
|
||||
->defaultLowOutputLatency; /* Low latency. */
|
||||
err = Pa_OpenStream( &stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
1024, /* frames per buffer */
|
||||
flags,
|
||||
sineCallback,
|
||||
(void*)data );
|
||||
if (err != paNoError)
|
||||
goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if (err != paNoError)
|
||||
goto done;
|
||||
|
||||
Pa_Sleep( NUM_SECONDS * 1000 );
|
||||
printf("CPULoad = %8.6f\n", Pa_GetStreamCpuLoad(stream));
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
done:
|
||||
Pa_Sleep( 250 ); /* Just a small silence. */
|
||||
Pa_Terminate();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
paTestData DATA;
|
||||
int i;
|
||||
float amplitude = 4.0 / (1<<15);
|
||||
|
||||
printf("PortAudio Test: output EXTREMELY QUIET sine wave with and without dithering.\n");
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
DATA.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
printf("\nNo treatment..\n"); fflush(stdout);
|
||||
err = PlaySine( &DATA, paClipOff | paDitherOff, amplitude );
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
printf("\nClip..\n");
|
||||
fflush(stdout);
|
||||
err = PlaySine( &DATA, paDitherOff, amplitude );
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
printf("\nClip and Dither..\n");
|
||||
fflush(stdout);
|
||||
err = PlaySine( &DATA, paNoFlag, amplitude );
|
||||
done:
|
||||
if (err)
|
||||
{
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
err = 1; /* Though PlaySine() already called Pa_Terminate(), */
|
||||
} /* we may still call Pa_GetErrorText(). */
|
||||
else
|
||||
printf("\n(Don't forget to turn the VOLUME DOWN after listening so carefully.)\n");
|
||||
return err; /* 0 or 1. */
|
||||
}
|
||||
@ -1,152 +0,0 @@
|
||||
/** @file patest_hang.c
|
||||
@brief Play a sine then hang audio callback to test watchdog.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (1024)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
int sleepFor;
|
||||
double phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
double phaseInc = 0.02;
|
||||
double phase = data->phase;
|
||||
|
||||
(void) inputBuffer; /* Prevent unused argument warning. */
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
phase += phaseInc;
|
||||
if( phase > TWOPI ) phase -= TWOPI;
|
||||
/* This is not a very efficient way to calc sines. */
|
||||
*out++ = (float) sin( phase ); /* mono */
|
||||
}
|
||||
|
||||
if( data->sleepFor > 0 )
|
||||
{
|
||||
Pa_Sleep( data->sleepFor );
|
||||
}
|
||||
|
||||
data->phase = phase;
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream* stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
int i;
|
||||
paTestData data = {0};
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n",
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
|
||||
outputParameters.channelCount = 1; /* Mono output. */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point. */
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)
|
||||
->defaultLowOutputLatency;
|
||||
err = Pa_OpenStream(&stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* No out of range samples. */
|
||||
patestCallback,
|
||||
&data);
|
||||
if (err != paNoError) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Gradually increase sleep time. */
|
||||
/* Was: for( i=0; i<10000; i+= 1000 ) */
|
||||
for(i=0; i <= 1000; i += 100)
|
||||
{
|
||||
printf("Sleep for %d milliseconds in audio callback.\n", i );
|
||||
data.sleepFor = i;
|
||||
Pa_Sleep( ((i<1000) ? 1000 : i) );
|
||||
}
|
||||
|
||||
printf("Suffer for 10 seconds.\n");
|
||||
Pa_Sleep( 10000 );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,224 +0,0 @@
|
||||
/** @file patest_in_overflow.c
|
||||
@brief Count input overflows (using paInputOverflow flag) under
|
||||
overloaded and normal conditions.
|
||||
This test uses the same method to overload the stream as does
|
||||
patest_out_underflow.c -- it generates sine waves until the cpu load
|
||||
exceeds a certain level. However this test is only concerned with
|
||||
input and so doesn't ouput any sound.
|
||||
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2004 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define MAX_SINES (500)
|
||||
#define MAX_LOAD (1.2)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (512)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
int sineCount;
|
||||
double phases[MAX_SINES];
|
||||
int countOverflows;
|
||||
int inputOverflowCount;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float out; /* variable to hold dummy output */
|
||||
unsigned long i;
|
||||
int j;
|
||||
int finished = paContinue;
|
||||
(void) timeInfo; /* Prevent unused variable warning. */
|
||||
(void) inputBuffer; /* Prevent unused variable warning. */
|
||||
(void) outputBuffer; /* Prevent unused variable warning. */
|
||||
|
||||
if( data->countOverflows && (statusFlags & paInputOverflow) )
|
||||
data->inputOverflowCount++;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
float output = 0.0;
|
||||
double phaseInc = 0.02;
|
||||
double phase;
|
||||
|
||||
for( j=0; j<data->sineCount; j++ )
|
||||
{
|
||||
/* Advance phase of next oscillator. */
|
||||
phase = data->phases[j];
|
||||
phase += phaseInc;
|
||||
if( phase > TWOPI ) phase -= TWOPI;
|
||||
|
||||
phaseInc *= 1.02;
|
||||
if( phaseInc > 0.5 ) phaseInc *= 0.5;
|
||||
|
||||
/* This is not a very efficient way to calc sines. */
|
||||
output += (float) sin( phase );
|
||||
data->phases[j] = phase;
|
||||
}
|
||||
/* this is an input-only stream so we don't actually use the output */
|
||||
out = (float) (output / data->sineCount);
|
||||
(void) out; /* suppress unused variable warning*/
|
||||
}
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters inputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
int safeSineCount, stressedSineCount;
|
||||
int safeOverflowCount, stressedOverflowCount;
|
||||
paTestData data = {0};
|
||||
double load;
|
||||
|
||||
|
||||
printf("PortAudio Test: input only, no sound output. Load callback by performing calculations, count input overflows. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER, (float)MAX_LOAD );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
inputParameters.channelCount = 1; /* mono output */
|
||||
inputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
NULL, /* no output */
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Establishing load conditions...\n" );
|
||||
|
||||
/* Determine number of sines required to get to 50% */
|
||||
do
|
||||
{
|
||||
data.sineCount++;
|
||||
Pa_Sleep( 100 );
|
||||
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
|
||||
}
|
||||
while( load < 0.5 && data.sineCount < (MAX_SINES-1));
|
||||
|
||||
safeSineCount = data.sineCount;
|
||||
|
||||
/* Calculate target stress value then ramp up to that level*/
|
||||
stressedSineCount = (int) (2.0 * data.sineCount * MAX_LOAD );
|
||||
if( stressedSineCount > MAX_SINES )
|
||||
stressedSineCount = MAX_SINES;
|
||||
for( ; data.sineCount < stressedSineCount; data.sineCount++ )
|
||||
{
|
||||
Pa_Sleep( 100 );
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("STRESSING: sineCount = %d, CPU load = %f\n", data.sineCount, load );
|
||||
}
|
||||
|
||||
printf("Counting overflows for 5 seconds.\n");
|
||||
data.countOverflows = 1;
|
||||
Pa_Sleep( 5000 );
|
||||
|
||||
stressedOverflowCount = data.inputOverflowCount;
|
||||
|
||||
data.countOverflows = 0;
|
||||
data.sineCount = safeSineCount;
|
||||
|
||||
printf("Resuming safe load...\n");
|
||||
Pa_Sleep( 1500 );
|
||||
data.inputOverflowCount = 0;
|
||||
Pa_Sleep( 1500 );
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
|
||||
|
||||
printf("Counting overflows for 5 seconds.\n");
|
||||
data.countOverflows = 1;
|
||||
Pa_Sleep( 5000 );
|
||||
|
||||
safeOverflowCount = data.inputOverflowCount;
|
||||
|
||||
printf("Stop stream.\n");
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
|
||||
if( stressedOverflowCount == 0 )
|
||||
printf("Test failed, no input overflows detected under stress.\n");
|
||||
else if( safeOverflowCount != 0 )
|
||||
printf("Test failed, %d unexpected overflows detected under safe load.\n", safeOverflowCount);
|
||||
else
|
||||
printf("Test passed, %d expected input overflows detected under stress, 0 unexpected overflows detected under safe load.\n", stressedOverflowCount );
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,182 +0,0 @@
|
||||
/** @file
|
||||
@brief Hear the latency caused by big buffers.
|
||||
Play a sine wave and change frequency based on letter input.
|
||||
@author Phil Burk <philburk@softsynth.com>, and Darren Gibbs
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
|
||||
#define MIN_FREQ (100.0f)
|
||||
#define CalcPhaseIncrement(freq) ((freq)/SAMPLE_RATE)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (400)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE + 1]; /* add one for guard point for interpolation */
|
||||
float phase_increment;
|
||||
float left_phase;
|
||||
float right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
float LookupSine( paTestData *data, float phase );
|
||||
/* Convert phase between and 1.0 to sine value
|
||||
* using linear interpolation.
|
||||
*/
|
||||
float LookupSine( paTestData *data, float phase )
|
||||
{
|
||||
float fIndex = phase*TABLE_SIZE;
|
||||
int index = (int) fIndex;
|
||||
float fract = fIndex - index;
|
||||
float lo = data->sine[index];
|
||||
float hi = data->sine[index+1];
|
||||
float val = lo + fract*(hi-lo);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
int i;
|
||||
|
||||
(void) inputBuffer; /* Prevent unused variable warning. */
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = LookupSine(data, data->left_phase); /* left */
|
||||
*out++ = LookupSine(data, data->right_phase); /* right */
|
||||
data->left_phase += data->phase_increment;
|
||||
if( data->left_phase >= 1.0f ) data->left_phase -= 1.0f;
|
||||
data->right_phase += (data->phase_increment * 1.5f); /* fifth above */
|
||||
if( data->right_phase >= 1.0f ) data->right_phase -= 1.0f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream *stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
int done = 0;
|
||||
|
||||
printf("PortAudio Test: enter letter then hit ENTER.\n" );
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = 0.90f * (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.sine[TABLE_SIZE] = data.sine[0]; /* set guard point. */
|
||||
data.left_phase = data.right_phase = 0.0;
|
||||
data.phase_increment = CalcPhaseIncrement(MIN_FREQ);
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
printf("PortAudio Test: output device = %d\n", OUTPUT_DEVICE );
|
||||
|
||||
outputParameters.device = OUTPUT_DEVICE;
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
printf("Requested output latency = %.4f seconds.\n", outputParameters.suggestedLatency );
|
||||
printf("%d frames per buffer.\n.", FRAMES_PER_BUFFER );
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff|paDitherOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Play ASCII keyboard. Hit 'q' to stop. (Use RETURN key on Mac)\n");
|
||||
fflush(stdout);
|
||||
while ( !done )
|
||||
{
|
||||
float freq;
|
||||
int index;
|
||||
char c;
|
||||
do
|
||||
{
|
||||
c = getchar();
|
||||
}
|
||||
while( c < ' '); /* Strip white space and control chars. */
|
||||
|
||||
if( c == 'q' ) done = 1;
|
||||
index = c % 26;
|
||||
freq = MIN_FREQ + (index * 40.0);
|
||||
data.phase_increment = CalcPhaseIncrement(freq);
|
||||
}
|
||||
printf("Call Pa_StopStream()\n");
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,173 +0,0 @@
|
||||
/** @file patest_leftright.c
|
||||
@brief Play different tone sine waves that
|
||||
alternate between left and right channel.
|
||||
|
||||
The low tone should be on the left channel.
|
||||
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (8)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (512)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
int toggle;
|
||||
int countDown;
|
||||
}
|
||||
paTestData;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer,
|
||||
void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
/* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
if( data->toggle )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
else
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
}
|
||||
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
|
||||
if( data->countDown < 0 )
|
||||
{
|
||||
data->countDown = SAMPLE_RATE;
|
||||
data->toggle = !data->toggle;
|
||||
}
|
||||
data->countDown -= framesPerBuffer;
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream *stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
int timeout;
|
||||
|
||||
printf("Play different tone sine waves that alternate between left and right channel.\n");
|
||||
printf("The low tone should be on the left channel.\n");
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.left_phase = data.right_phase = data.toggle = 0;
|
||||
data.countDown = SAMPLE_RATE;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream( &stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters, /* As above. */
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for several seconds.\n");
|
||||
timeout = NUM_SECONDS * 4;
|
||||
while( timeout > 0 )
|
||||
{
|
||||
Pa_Sleep( 300 ); /*(Irix very much likes sleeps <= 1000 ms.)*/
|
||||
timeout -= 1;
|
||||
}
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,140 +0,0 @@
|
||||
/** @file patest_longsine.c
|
||||
@brief Play a sine wave until ENTER hit.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#define SAMPLE_RATE (44100)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback(const void* inputBuffer,
|
||||
void* outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void* userData)
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned int i;
|
||||
(void) inputBuffer; /* Prevent unused argument warning. */
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
printf("PortAudio Test: output sine wave.\n");
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.left_phase = data.right_phase = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream( &stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters, /* As above. */
|
||||
SAMPLE_RATE,
|
||||
256, /* Frames per buffer. */
|
||||
paClipOff, /* No out of range samples expected. */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Hit ENTER to stop program.\n");
|
||||
getchar();
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,198 +0,0 @@
|
||||
/** @file patest_many.c
|
||||
@brief Start and stop the PortAudio Driver multiple times.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#define NUM_SECONDS (1)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
short sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
unsigned int sampsToGo;
|
||||
}
|
||||
paTestData;
|
||||
PaError TestOnce( void );
|
||||
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData );
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
short *out = (short*)outputBuffer;
|
||||
unsigned int i;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent "unused variable" warnings. */
|
||||
|
||||
if( data->sampsToGo < framesPerBuffer )
|
||||
{
|
||||
/* final buffer... */
|
||||
|
||||
for( i=0; i<data->sampsToGo; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
data->sampsToGo -= framesPerBuffer;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
#ifdef MACINTOSH
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
PaError err;
|
||||
int numLoops = 10;
|
||||
printf("Loop %d times.\n", numLoops );
|
||||
for( i=0; i<numLoops; i++ )
|
||||
{
|
||||
printf("Loop %d out of %d.\n", i+1, numLoops );
|
||||
err = TestOnce();
|
||||
if( err < 0 ) return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int main(int argc, char **argv);
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
PaError err;
|
||||
int i, numLoops = 10;
|
||||
if( argc > 1 )
|
||||
{
|
||||
numLoops = atoi(argv[1]);
|
||||
}
|
||||
for( i=0; i<numLoops; i++ )
|
||||
{
|
||||
printf("Loop %d out of %d.\n", i+1, numLoops );
|
||||
err = TestOnce();
|
||||
if( err < 0 ) return 1;
|
||||
}
|
||||
printf("Test complete.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
PaError TestOnce( void )
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
int totalSamps;
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (short) (32767.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
|
||||
}
|
||||
data.left_phase = data.right_phase = 0;
|
||||
data.sampsToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paInt16;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
1024, /* frames per buffer */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patest1Callback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Waiting for sound to finish.\n");
|
||||
Pa_Sleep(1000);
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
return paNoError;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,204 +0,0 @@
|
||||
/** @file patest_maxsines.c
|
||||
@brief How many sine waves can we calculate and play in less than 80% CPU Load.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define MAX_SINES (500)
|
||||
#define MAX_USAGE (0.8)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FREQ_TO_PHASE_INC(freq) (freq/(float)SAMPLE_RATE)
|
||||
|
||||
#define MIN_PHASE_INC FREQ_TO_PHASE_INC(200.0f)
|
||||
#define MAX_PHASE_INC (MIN_PHASE_INC * (1 << 5))
|
||||
|
||||
#define FRAMES_PER_BUFFER (512)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
#define TABLE_SIZE (512)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
int numSines;
|
||||
float sine[TABLE_SIZE + 1]; /* add one for guard point for interpolation */
|
||||
float phases[MAX_SINES];
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* Convert phase between and 1.0 to sine value
|
||||
* using linear interpolation.
|
||||
*/
|
||||
float LookupSine( paTestData *data, float phase );
|
||||
float LookupSine( paTestData *data, float phase )
|
||||
{
|
||||
float fIndex = phase*TABLE_SIZE;
|
||||
int index = (int) fIndex;
|
||||
float fract = fIndex - index;
|
||||
float lo = data->sine[index];
|
||||
float hi = data->sine[index+1];
|
||||
float val = lo + fract*(hi-lo);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback(const void* inputBuffer,
|
||||
void* outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void* userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
float outSample;
|
||||
float scaler;
|
||||
int numForScale;
|
||||
unsigned long i;
|
||||
int j;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent unused argument warning. */
|
||||
|
||||
/* Determine amplitude scaling factor */
|
||||
numForScale = data->numSines;
|
||||
if( numForScale < 8 ) numForScale = 8; /* prevent pops at beginning */
|
||||
scaler = 1.0f / numForScale;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
float output = 0.0;
|
||||
float phaseInc = MIN_PHASE_INC;
|
||||
float phase;
|
||||
for( j=0; j<data->numSines; j++ )
|
||||
{
|
||||
/* Advance phase of next oscillator. */
|
||||
phase = data->phases[j];
|
||||
phase += phaseInc;
|
||||
if( phase >= 1.0 ) phase -= 1.0;
|
||||
|
||||
output += LookupSine(data, phase);
|
||||
data->phases[j] = phase;
|
||||
|
||||
phaseInc *= 1.02f;
|
||||
if( phaseInc > MAX_PHASE_INC ) phaseInc = MIN_PHASE_INC;
|
||||
}
|
||||
|
||||
outSample = (float) (output * scaler);
|
||||
*out++ = outSample; /* Left */
|
||||
*out++ = outSample; /* Right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
PaStream* stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
paTestData data = {0};
|
||||
double load;
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.sine[TABLE_SIZE] = data.sine[0]; /* set guard point */
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
|
||||
outputParameters.channelCount = 2; /* Stereo output. */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)
|
||||
->defaultHighOutputLatency;
|
||||
err = Pa_OpenStream(&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* No out of range samples should occur. */
|
||||
patestCallback,
|
||||
&data);
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
/* Play an increasing number of sine waves until we hit MAX_USAGE */
|
||||
do {
|
||||
data.numSines++;
|
||||
Pa_Sleep(200);
|
||||
load = Pa_GetStreamCpuLoad(stream);
|
||||
printf("numSines = %d, CPU load = %f\n", data.numSines, load );
|
||||
fflush(stdout);
|
||||
} while((load < MAX_USAGE) && (data.numSines < MAX_SINES));
|
||||
|
||||
Pa_Sleep(2000); /* Stay for 2 seconds around 80% CPU. */
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* patest_sine.c
|
||||
* Play a monophonic sine wave using the Portable Audio api for several seconds.
|
||||
*
|
||||
* Authors:
|
||||
* Ross Bencina <rossb@audiomulch.com>
|
||||
* Phil Burk <philburk@softsynth.com>
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (10)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define AMPLITUDE (0.8)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
#define OUTPUT_DEVICE Pa_GetDefaultOutputDevice()
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
/* avoid unused variable warnings */
|
||||
(void) inputBuffer;
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->phase]; /* left */
|
||||
data->phase += 1;
|
||||
if( data->phase >= TABLE_SIZE ) data->phase -= TABLE_SIZE;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
printf("PortAudio Test: output MONO sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) (AMPLITUDE * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
|
||||
}
|
||||
data.phase = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = OUTPUT_DEVICE;
|
||||
outputParameters.channelCount = 1; /* MONO output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS ); fflush(stdout);
|
||||
Pa_Sleep( NUM_SECONDS * 1000 );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* patest_sine.c
|
||||
* Play a monophonic sine wave using the Portable Audio api for several seconds.
|
||||
*
|
||||
* Authors:
|
||||
* Ross Bencina <rossb@audiomulch.com>
|
||||
* Phil Burk <philburk@softsynth.com>
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#include "pa_asio.h"
|
||||
|
||||
#define NUM_SECONDS (10)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define AMPLITUDE (0.8)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
#define OUTPUT_DEVICE Pa_GetDefaultOutputDevice()
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
/* avoid unused variable warnings */
|
||||
(void) inputBuffer;
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->phase]; /* left */
|
||||
data->phase += 1;
|
||||
if( data->phase >= TABLE_SIZE ) data->phase -= TABLE_SIZE;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaAsioStreamInfo asioOutputInfo;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int outputChannelSelectors[1];
|
||||
int i;
|
||||
printf("PortAudio Test: output MONO sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) (AMPLITUDE * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
|
||||
}
|
||||
data.phase = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = OUTPUT_DEVICE;
|
||||
outputParameters.channelCount = 1; /* MONO output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
|
||||
asioOutputInfo.size = sizeof(PaAsioStreamInfo);
|
||||
asioOutputInfo.hostApiType = paASIO;
|
||||
asioOutputInfo.version = 1;
|
||||
asioOutputInfo.flags = paAsioUseChannelSelectors;
|
||||
outputChannelSelectors[0] = 1; /* select the second (right) ASIO device channel */
|
||||
asioOutputInfo.channelSelectors = outputChannelSelectors;
|
||||
outputParameters.hostApiSpecificStreamInfo = &asioOutputInfo;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS ); fflush(stdout);
|
||||
Pa_Sleep( NUM_SECONDS * 1000 );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,194 +0,0 @@
|
||||
/** @file patest_multi_sine.c
|
||||
@brief Play a different sine wave on each channel.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define FREQ_INCR (300.0 / SAMPLE_RATE)
|
||||
#define MAX_CHANNELS (64)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short interleaved; /* Nonzero for interleaved / zero for non-interleaved. */
|
||||
int numChannels; /* Actually used. */
|
||||
double phases[MAX_CHANNELS]; /* Each channel gets its' own frequency. */
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback(const void* inputBuffer,
|
||||
void* outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void* userData)
|
||||
{
|
||||
int frameIndex, channelIndex;
|
||||
float** outputs = (float**)outputBuffer;
|
||||
paTestData* data = (paTestData*)userData;
|
||||
|
||||
(void) inputBuffer; /* Prevent unused arg warning. */
|
||||
if (data->interleaved)
|
||||
{
|
||||
float *out = (float*)outputBuffer; /* interleaved version */
|
||||
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
|
||||
{
|
||||
for( channelIndex=0; channelIndex<data->numChannels; channelIndex++ )
|
||||
{
|
||||
/* Output sine wave on every channel. */
|
||||
*out++ = (float) sin(data->phases[channelIndex]);
|
||||
|
||||
/* Play each channel at a higher frequency. */
|
||||
data->phases[channelIndex] += FREQ_INCR * (4 + channelIndex);
|
||||
if( data->phases[channelIndex] >= (2.0 * M_PI) ) data->phases[channelIndex] -= (2.0 * M_PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
|
||||
{
|
||||
for( channelIndex=0; channelIndex<data->numChannels; channelIndex++ )
|
||||
{
|
||||
/* Output sine wave on every channel. */
|
||||
outputs[channelIndex][frameIndex] = (float) sin(data->phases[channelIndex]);
|
||||
|
||||
/* Play each channel at a higher frequency. */
|
||||
data->phases[channelIndex] += FREQ_INCR * (4 + channelIndex);
|
||||
if( data->phases[channelIndex] >= (2.0 * M_PI) ) data->phases[channelIndex] -= (2.0 * M_PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int test(short interleaved)
|
||||
{
|
||||
PaStream* stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
const PaDeviceInfo* pdi;
|
||||
paTestData data;
|
||||
short n;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device, max channels. */
|
||||
pdi = Pa_GetDeviceInfo(outputParameters.device);
|
||||
outputParameters.channelCount = pdi->maxOutputChannels;
|
||||
if (outputParameters.channelCount > MAX_CHANNELS)
|
||||
outputParameters.channelCount = MAX_CHANNELS;
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = pdi->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
data.interleaved = interleaved;
|
||||
data.numChannels = outputParameters.channelCount;
|
||||
for (n = 0; n < data.numChannels; n++)
|
||||
data.phases[n] = 0.0; /* Phases wrap and maybe don't need initialisation. */
|
||||
printf("%d ", data.numChannels);
|
||||
if (interleaved)
|
||||
printf("interleaved ");
|
||||
else
|
||||
{
|
||||
printf(" non-interleaved ");
|
||||
outputParameters.sampleFormat |= paNonInterleaved;
|
||||
}
|
||||
printf("channels.\n");
|
||||
|
||||
err = Pa_OpenStream(&stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE, /* Sample rate. */
|
||||
FRAMES_PER_BUFFER, /* Frames per buffer. */
|
||||
paClipOff, /* Samples never out of range, no clipping. */
|
||||
patestCallback,
|
||||
&data);
|
||||
if (err == paNoError)
|
||||
{
|
||||
err = Pa_StartStream(stream);
|
||||
if (err == paNoError)
|
||||
{
|
||||
printf("Hit ENTER to stop this test.\n");
|
||||
getchar();
|
||||
err = Pa_StopStream(stream);
|
||||
}
|
||||
Pa_CloseStream( stream );
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
|
||||
printf("PortAudio Test: output sine wave on each channel.\n" );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if (err != paNoError)
|
||||
goto done;
|
||||
|
||||
err = test(1); /* 1 means interleaved. */
|
||||
if (err != paNoError)
|
||||
goto done;
|
||||
|
||||
err = test(0); /* 0 means not interleaved. */
|
||||
if (err != paNoError)
|
||||
goto done;
|
||||
|
||||
printf("Test finished.\n");
|
||||
done:
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "An error occured while using the portaudio stream\n");
|
||||
fprintf(stderr, "Error number: %d\n", err );
|
||||
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
|
||||
}
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
}
|
||||
@ -1,217 +0,0 @@
|
||||
/** @file patest_out_underflow.c
|
||||
@brief Count output underflows (using paOutputUnderflow flag)
|
||||
under overloaded and normal conditions.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2004 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define MAX_SINES (500)
|
||||
#define MAX_LOAD (1.2)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (512)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
int sineCount;
|
||||
double phases[MAX_SINES];
|
||||
int countUnderflows;
|
||||
int outputUnderflowCount;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int j;
|
||||
int finished = paContinue;
|
||||
(void) timeInfo; /* Prevent unused variable warning. */
|
||||
(void) inputBuffer; /* Prevent unused variable warning. */
|
||||
|
||||
|
||||
if( data->countUnderflows && (statusFlags & paOutputUnderflow) )
|
||||
data->outputUnderflowCount++;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
float output = 0.0;
|
||||
double phaseInc = 0.02;
|
||||
double phase;
|
||||
|
||||
for( j=0; j<data->sineCount; j++ )
|
||||
{
|
||||
/* Advance phase of next oscillator. */
|
||||
phase = data->phases[j];
|
||||
phase += phaseInc;
|
||||
if( phase > TWOPI ) phase -= TWOPI;
|
||||
|
||||
phaseInc *= 1.02;
|
||||
if( phaseInc > 0.5 ) phaseInc *= 0.5;
|
||||
|
||||
/* This is not a very efficient way to calc sines. */
|
||||
output += (float) sin( phase );
|
||||
data->phases[j] = phase;
|
||||
}
|
||||
*out++ = (float) (output / data->sineCount);
|
||||
}
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
int safeSineCount, stressedSineCount;
|
||||
int safeUnderflowCount, stressedUnderflowCount;
|
||||
paTestData data = {0};
|
||||
double load;
|
||||
|
||||
|
||||
printf("PortAudio Test: output sine waves, count underflows. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER, (float)MAX_LOAD );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 1; /* mono output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Establishing load conditions...\n" );
|
||||
|
||||
/* Determine number of sines required to get to 50% */
|
||||
do
|
||||
{
|
||||
data.sineCount++;
|
||||
Pa_Sleep( 100 );
|
||||
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
|
||||
}
|
||||
while( load < 0.5 && data.sineCount < (MAX_SINES-1));
|
||||
|
||||
safeSineCount = data.sineCount;
|
||||
|
||||
/* Calculate target stress value then ramp up to that level*/
|
||||
stressedSineCount = (int) (2.0 * data.sineCount * MAX_LOAD );
|
||||
if( stressedSineCount > MAX_SINES )
|
||||
stressedSineCount = MAX_SINES;
|
||||
for( ; data.sineCount < stressedSineCount; data.sineCount++ )
|
||||
{
|
||||
Pa_Sleep( 100 );
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("STRESSING: sineCount = %d, CPU load = %f\n", data.sineCount, load );
|
||||
}
|
||||
|
||||
printf("Counting underflows for 5 seconds.\n");
|
||||
data.countUnderflows = 1;
|
||||
Pa_Sleep( 5000 );
|
||||
|
||||
stressedUnderflowCount = data.outputUnderflowCount;
|
||||
|
||||
data.countUnderflows = 0;
|
||||
data.sineCount = safeSineCount;
|
||||
|
||||
printf("Resuming safe load...\n");
|
||||
Pa_Sleep( 1500 );
|
||||
data.outputUnderflowCount = 0;
|
||||
Pa_Sleep( 1500 );
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
|
||||
|
||||
printf("Counting underflows for 5 seconds.\n");
|
||||
data.countUnderflows = 1;
|
||||
Pa_Sleep( 5000 );
|
||||
|
||||
safeUnderflowCount = data.outputUnderflowCount;
|
||||
|
||||
printf("Stop stream.\n");
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
|
||||
if( stressedUnderflowCount == 0 )
|
||||
printf("Test failed, no output underflows detected under stress.\n");
|
||||
else if( safeUnderflowCount != 0 )
|
||||
printf("Test failed, %d unexpected underflows detected under safe load.\n", safeUnderflowCount);
|
||||
else
|
||||
printf("Test passed, %d expected output underflows detected under stress, 0 unexpected underflows detected under safe load.\n", stressedUnderflowCount );
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,269 +0,0 @@
|
||||
/** @file patest_pink.c
|
||||
@brief Generate Pink Noise using Gardner method.
|
||||
|
||||
Optimization suggested by James McCartney uses a tree
|
||||
to select which random value to replace.
|
||||
<pre>
|
||||
x x x x x x x x x x x x x x x x
|
||||
x x x x x x x x
|
||||
x x x x
|
||||
x x
|
||||
x
|
||||
</pre>
|
||||
Tree is generated by counting trailing zeros in an increasing index.
|
||||
When the index is zero, no random number is selected.
|
||||
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define PINK_MAX_RANDOM_ROWS (30)
|
||||
#define PINK_RANDOM_BITS (24)
|
||||
#define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long pink_Rows[PINK_MAX_RANDOM_ROWS];
|
||||
long pink_RunningSum; /* Used to optimize summing of generators. */
|
||||
int pink_Index; /* Incremented each sample. */
|
||||
int pink_IndexMask; /* Index wrapped by ANDing with this mask. */
|
||||
float pink_Scalar; /* Used to scale within range of -1.0 to +1.0 */
|
||||
}
|
||||
PinkNoise;
|
||||
|
||||
/* Prototypes */
|
||||
static unsigned long GenerateRandomNumber( void );
|
||||
void InitializePinkNoise( PinkNoise *pink, int numRows );
|
||||
float GeneratePinkNoise( PinkNoise *pink );
|
||||
|
||||
/************************************************************/
|
||||
/* Calculate pseudo-random 32 bit number based on linear congruential method. */
|
||||
static unsigned long GenerateRandomNumber( void )
|
||||
{
|
||||
/* Change this seed for different random sequences. */
|
||||
static unsigned long randSeed = 22222;
|
||||
randSeed = (randSeed * 196314165) + 907633515;
|
||||
return randSeed;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
/* Setup PinkNoise structure for N rows of generators. */
|
||||
void InitializePinkNoise( PinkNoise *pink, int numRows )
|
||||
{
|
||||
int i;
|
||||
long pmax;
|
||||
pink->pink_Index = 0;
|
||||
pink->pink_IndexMask = (1<<numRows) - 1;
|
||||
/* Calculate maximum possible signed random value. Extra 1 for white noise always added. */
|
||||
pmax = (numRows + 1) * (1<<(PINK_RANDOM_BITS-1));
|
||||
pink->pink_Scalar = 1.0f / pmax;
|
||||
/* Initialize rows. */
|
||||
for( i=0; i<numRows; i++ ) pink->pink_Rows[i] = 0;
|
||||
pink->pink_RunningSum = 0;
|
||||
}
|
||||
|
||||
#define PINK_MEASURE
|
||||
#ifdef PINK_MEASURE
|
||||
float pinkMax = -999.0;
|
||||
float pinkMin = 999.0;
|
||||
#endif
|
||||
|
||||
/* Generate Pink noise values between -1.0 and +1.0 */
|
||||
float GeneratePinkNoise( PinkNoise *pink )
|
||||
{
|
||||
long newRandom;
|
||||
long sum;
|
||||
float output;
|
||||
/* Increment and mask index. */
|
||||
pink->pink_Index = (pink->pink_Index + 1) & pink->pink_IndexMask;
|
||||
/* If index is zero, don't update any random values. */
|
||||
if( pink->pink_Index != 0 )
|
||||
{
|
||||
/* Determine how many trailing zeros in PinkIndex. */
|
||||
/* This algorithm will hang if n==0 so test first. */
|
||||
int numZeros = 0;
|
||||
int n = pink->pink_Index;
|
||||
while( (n & 1) == 0 )
|
||||
{
|
||||
n = n >> 1;
|
||||
numZeros++;
|
||||
}
|
||||
/* Replace the indexed ROWS random value.
|
||||
* Subtract and add back to RunningSum instead of adding all the random
|
||||
* values together. Only one changes each time.
|
||||
*/
|
||||
pink->pink_RunningSum -= pink->pink_Rows[numZeros];
|
||||
newRandom = ((long)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
|
||||
pink->pink_RunningSum += newRandom;
|
||||
pink->pink_Rows[numZeros] = newRandom;
|
||||
}
|
||||
|
||||
/* Add extra white noise value. */
|
||||
newRandom = ((long)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
|
||||
sum = pink->pink_RunningSum + newRandom;
|
||||
/* Scale to range of -1.0 to 0.9999. */
|
||||
output = pink->pink_Scalar * sum;
|
||||
#ifdef PINK_MEASURE
|
||||
/* Check Min/Max */
|
||||
if( output > pinkMax ) pinkMax = output;
|
||||
else if( output < pinkMin ) pinkMin = output;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
#define PINK_TEST
|
||||
#ifdef PINK_TEST
|
||||
|
||||
/* Context for callback routine. */
|
||||
typedef struct
|
||||
{
|
||||
PinkNoise leftPink;
|
||||
PinkNoise rightPink;
|
||||
unsigned int sampsToGo;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback(const void* inputBuffer,
|
||||
void* outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void* userData)
|
||||
{
|
||||
int finished;
|
||||
int i;
|
||||
int numFrames;
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
(void) inputBuffer; /* Prevent "unused variable" warnings. */
|
||||
|
||||
/* Are we almost at end. */
|
||||
if( data->sampsToGo < framesPerBuffer )
|
||||
{
|
||||
numFrames = data->sampsToGo;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
numFrames = framesPerBuffer;
|
||||
finished = 0;
|
||||
}
|
||||
for( i=0; i<numFrames; i++ )
|
||||
{
|
||||
*out++ = GeneratePinkNoise( &data->leftPink );
|
||||
*out++ = GeneratePinkNoise( &data->rightPink );
|
||||
}
|
||||
data->sampsToGo -= numFrames;
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream* stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
PaStreamParameters outputParameters;
|
||||
int totalSamps;
|
||||
static const double SR = 44100.0;
|
||||
static const int FPB = 2048; /* Frames per buffer: 46 ms buffers. */
|
||||
|
||||
/* Initialize two pink noise signals with different numbers of rows. */
|
||||
InitializePinkNoise( &data.leftPink, 12 );
|
||||
InitializePinkNoise( &data.rightPink, 16 );
|
||||
|
||||
/* Look at a few values. */
|
||||
{
|
||||
int i;
|
||||
float pink;
|
||||
for( i=0; i<20; i++ )
|
||||
{
|
||||
pink = GeneratePinkNoise( &data.leftPink );
|
||||
printf("Pink = %f\n", pink );
|
||||
}
|
||||
}
|
||||
|
||||
data.sampsToGo = totalSamps = (int)(60.0 * SR); /* Play a whole minute. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Open a stereo PortAudio stream so we can hear the result. */
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Take the default output device. */
|
||||
outputParameters.channelCount = 2; /* Stereo output, most likely supported. */
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
|
||||
outputParameters.suggestedLatency =
|
||||
Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
|
||||
err = Pa_OpenStream(&stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters,
|
||||
SR, /* Sample rate. */
|
||||
FPB, /* Frames per buffer. */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data);
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Stereo pink noise for one minute...\n");
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
#ifdef PINK_MEASURE
|
||||
printf("Pink min = %f, max = %f\n", pinkMin, pinkMax );
|
||||
#endif
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return 0;
|
||||
}
|
||||
#endif /* PINK_TEST */
|
||||
@ -1,223 +0,0 @@
|
||||
/** @file patest_prime.c
|
||||
@brief Test stream priming mode.
|
||||
@author Ross Bencina http://www.audiomulch.com/~rossb
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#include "pa_util.h"
|
||||
|
||||
#define NUM_BEEPS (3)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define SAMPLE_PERIOD (1.0/44100.0)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define BEEP_DURATION (400)
|
||||
#define IDLE_DURATION (SAMPLE_RATE*2) /* 2 seconds */
|
||||
#define SLEEP_MSEC (50)
|
||||
|
||||
#define STATE_BKG_IDLE (0)
|
||||
#define STATE_BKG_BEEPING (1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float leftPhase;
|
||||
float rightPhase;
|
||||
int state;
|
||||
int beepCountdown;
|
||||
int idleCountdown;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
static void InitializeTestData( paTestData *testData )
|
||||
{
|
||||
testData->leftPhase = 0;
|
||||
testData->rightPhase = 0;
|
||||
testData->state = STATE_BKG_BEEPING;
|
||||
testData->beepCountdown = BEEP_DURATION;
|
||||
testData->idleCountdown = IDLE_DURATION;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo *timeInfo,
|
||||
PaStreamCallbackFlags statusFlags, void *userData )
|
||||
{
|
||||
/* Cast data passed through stream to our structure. */
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned int i;
|
||||
int result = paContinue;
|
||||
|
||||
/* supress unused parameter warnings */
|
||||
(void) inputBuffer;
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
switch( data->state )
|
||||
{
|
||||
case STATE_BKG_IDLE:
|
||||
*out++ = 0.0; /* left */
|
||||
*out++ = 0.0; /* right */
|
||||
--data->idleCountdown;
|
||||
|
||||
if( data->idleCountdown <= 0 ) result = paComplete;
|
||||
break;
|
||||
|
||||
case STATE_BKG_BEEPING:
|
||||
if( data->beepCountdown <= 0 )
|
||||
{
|
||||
data->state = STATE_BKG_IDLE;
|
||||
*out++ = 0.0; /* left */
|
||||
*out++ = 0.0; /* right */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Play sawtooth wave. */
|
||||
*out++ = data->leftPhase; /* left */
|
||||
*out++ = data->rightPhase; /* right */
|
||||
/* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
|
||||
data->leftPhase += 0.01f;
|
||||
/* When signal reaches top, drop back down. */
|
||||
if( data->leftPhase >= 1.0f ) data->leftPhase -= 2.0f;
|
||||
/* higher pitch so we can distinguish left and right. */
|
||||
data->rightPhase += 0.03f;
|
||||
if( data->rightPhase >= 1.0f ) data->rightPhase -= 2.0f;
|
||||
}
|
||||
--data->beepCountdown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
static PaError DoTest( int flags )
|
||||
{
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
PaStreamParameters outputParameters;
|
||||
|
||||
InitializeTestData( &data );
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice();
|
||||
outputParameters.channelCount = 2;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
outputParameters.sampleFormat = paFloat32;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
|
||||
|
||||
/* Open an audio I/O stream. */
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
paClipOff | flags, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("hear \"BEEP\"\n" );
|
||||
fflush(stdout);
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(SLEEP_MSEC);
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
return err;
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err = paNoError;
|
||||
int i;
|
||||
|
||||
/* Initialize library before making any other calls. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("PortAudio Test: Testing stream playback with no priming.\n");
|
||||
printf("PortAudio Test: you should see BEEP before you hear it.\n");
|
||||
printf("BEEP %d times.\n", NUM_BEEPS );
|
||||
|
||||
for( i=0; i< NUM_BEEPS; ++i )
|
||||
{
|
||||
err = DoTest( 0 );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("PortAudio Test: Testing stream playback with priming.\n");
|
||||
printf("PortAudio Test: you should see BEEP around the same time you hear it.\n");
|
||||
for( i=0; i< NUM_BEEPS; ++i )
|
||||
{
|
||||
err = DoTest( paPrimeOutputBuffersUsingStreamCallback );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("Test finished.\n");
|
||||
|
||||
Pa_Terminate();
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,229 +0,0 @@
|
||||
/** @file patest_read_record.c
|
||||
@brief Record input into an array; Save array to a file; Playback recorded
|
||||
data. Implemented using the blocking API (Pa_ReadStream(), Pa_WriteStream() )
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
@author Ross Bencina rossb@audiomulch.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (1024)
|
||||
#define NUM_SECONDS (5)
|
||||
#define NUM_CHANNELS (2)
|
||||
/* #define DITHER_FLAG (paDitherOff) */
|
||||
#define DITHER_FLAG (0) /**/
|
||||
|
||||
/* Select sample format. */
|
||||
#if 1
|
||||
#define PA_SAMPLE_TYPE paFloat32
|
||||
typedef float SAMPLE;
|
||||
#define SAMPLE_SILENCE (0.0f)
|
||||
#define PRINTF_S_FORMAT "%.8f"
|
||||
#elif 1
|
||||
#define PA_SAMPLE_TYPE paInt16
|
||||
typedef short SAMPLE;
|
||||
#define SAMPLE_SILENCE (0)
|
||||
#define PRINTF_S_FORMAT "%d"
|
||||
#elif 0
|
||||
#define PA_SAMPLE_TYPE paInt8
|
||||
typedef char SAMPLE;
|
||||
#define SAMPLE_SILENCE (0)
|
||||
#define PRINTF_S_FORMAT "%d"
|
||||
#else
|
||||
#define PA_SAMPLE_TYPE paUInt8
|
||||
typedef unsigned char SAMPLE;
|
||||
#define SAMPLE_SILENCE (128)
|
||||
#define PRINTF_S_FORMAT "%d"
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
SAMPLE *recordedSamples;
|
||||
int i;
|
||||
int totalFrames;
|
||||
int numSamples;
|
||||
int numBytes;
|
||||
SAMPLE max, average, val;
|
||||
|
||||
|
||||
printf("patest_read_record.c\n"); fflush(stdout);
|
||||
|
||||
totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */
|
||||
numSamples = totalFrames * NUM_CHANNELS;
|
||||
|
||||
numBytes = numSamples * sizeof(SAMPLE);
|
||||
recordedSamples = (SAMPLE *) malloc( numBytes );
|
||||
if( recordedSamples == NULL )
|
||||
{
|
||||
printf("Could not allocate record array.\n");
|
||||
exit(1);
|
||||
}
|
||||
for( i=0; i<numSamples; i++ ) recordedSamples[i] = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
inputParameters.channelCount = NUM_CHANNELS;
|
||||
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* Record some audio. -------------------------------------------- */
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
NULL, /* &outputParameters, */
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
NULL, /* no callback, use blocking API */
|
||||
NULL ); /* no callback, so no callback userData */
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Now recording!!\n"); fflush(stdout);
|
||||
|
||||
err = Pa_ReadStream( stream, recordedSamples, totalFrames );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Measure maximum peak amplitude. */
|
||||
max = 0;
|
||||
average = 0;
|
||||
for( i=0; i<numSamples; i++ )
|
||||
{
|
||||
val = recordedSamples[i];
|
||||
if( val < 0 ) val = -val; /* ABS */
|
||||
if( val > max )
|
||||
{
|
||||
max = val;
|
||||
}
|
||||
average += val;
|
||||
}
|
||||
|
||||
average = average / numSamples;
|
||||
|
||||
printf("Sample max amplitude = "PRINTF_S_FORMAT"\n", max );
|
||||
printf("Sample average = "PRINTF_S_FORMAT"\n", average );
|
||||
/* Was as below. Better choose at compile time because this
|
||||
keeps generating compiler-warnings:
|
||||
if( PA_SAMPLE_TYPE == paFloat32 )
|
||||
{
|
||||
printf("sample max amplitude = %f\n", max );
|
||||
printf("sample average = %f\n", average );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("sample max amplitude = %d\n", max );
|
||||
printf("sample average = %d\n", average );
|
||||
}
|
||||
*/
|
||||
/* Write recorded data to a file. */
|
||||
#if 0
|
||||
{
|
||||
FILE *fid;
|
||||
fid = fopen("recorded.raw", "wb");
|
||||
if( fid == NULL )
|
||||
{
|
||||
printf("Could not open file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite( recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
|
||||
fclose( fid );
|
||||
printf("Wrote data to 'recorded.raw'\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Playback recorded data. -------------------------------------------- */
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = NUM_CHANNELS;
|
||||
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
printf("Begin playback.\n"); fflush(stdout);
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
NULL, /* no callback, use blocking API */
|
||||
NULL ); /* no callback, so no callback userData */
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
if( stream )
|
||||
{
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Waiting for playback to finish.\n"); fflush(stdout);
|
||||
|
||||
err = Pa_WriteStream( stream, recordedSamples, totalFrames );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
printf("Done.\n"); fflush(stdout);
|
||||
}
|
||||
free( recordedSamples );
|
||||
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1,337 +0,0 @@
|
||||
/** @file patest_record.c
|
||||
@brief Record input into an array; Save array to a file; Playback recorded data.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (1024)
|
||||
#define NUM_SECONDS (5)
|
||||
#define NUM_CHANNELS (2)
|
||||
/* #define DITHER_FLAG (paDitherOff) */
|
||||
#define DITHER_FLAG (0) /**/
|
||||
|
||||
/* Select sample format. */
|
||||
#if 1
|
||||
#define PA_SAMPLE_TYPE paFloat32
|
||||
typedef float SAMPLE;
|
||||
#define SAMPLE_SILENCE (0.0f)
|
||||
#define PRINTF_S_FORMAT "%.8f"
|
||||
#elif 1
|
||||
#define PA_SAMPLE_TYPE paInt16
|
||||
typedef short SAMPLE;
|
||||
#define SAMPLE_SILENCE (0)
|
||||
#define PRINTF_S_FORMAT "%d"
|
||||
#elif 0
|
||||
#define PA_SAMPLE_TYPE paInt8
|
||||
typedef char SAMPLE;
|
||||
#define SAMPLE_SILENCE (0)
|
||||
#define PRINTF_S_FORMAT "%d"
|
||||
#else
|
||||
#define PA_SAMPLE_TYPE paUInt8
|
||||
typedef unsigned char SAMPLE;
|
||||
#define SAMPLE_SILENCE (128)
|
||||
#define PRINTF_S_FORMAT "%d"
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int frameIndex; /* Index into sample array. */
|
||||
int maxFrameIndex;
|
||||
SAMPLE *recordedSamples;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int recordCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
|
||||
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
|
||||
long framesToCalc;
|
||||
long i;
|
||||
int finished;
|
||||
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
|
||||
|
||||
(void) outputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
(void) userData;
|
||||
|
||||
if( framesLeft < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = framesLeft;
|
||||
finished = paComplete;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
finished = paContinue;
|
||||
}
|
||||
|
||||
if( inputBuffer == NULL )
|
||||
{
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*wptr++ = SAMPLE_SILENCE; /* left */
|
||||
if( NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE; /* right */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
|
||||
}
|
||||
}
|
||||
data->frameIndex += framesToCalc;
|
||||
return finished;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int playCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
|
||||
SAMPLE *wptr = (SAMPLE*)outputBuffer;
|
||||
unsigned int i;
|
||||
int finished;
|
||||
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
|
||||
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
(void) userData;
|
||||
|
||||
if( framesLeft < framesPerBuffer )
|
||||
{
|
||||
/* final buffer... */
|
||||
for( i=0; i<framesLeft; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
|
||||
}
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*wptr++ = 0; /* left */
|
||||
if( NUM_CHANNELS == 2 ) *wptr++ = 0; /* right */
|
||||
}
|
||||
data->frameIndex += framesLeft;
|
||||
finished = paComplete;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*wptr++ = *rptr++; /* left */
|
||||
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
|
||||
}
|
||||
data->frameIndex += framesPerBuffer;
|
||||
finished = paContinue;
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters inputParameters,
|
||||
outputParameters;
|
||||
PaStream* stream;
|
||||
PaError err = paNoError;
|
||||
paTestData data;
|
||||
int i;
|
||||
int totalFrames;
|
||||
int numSamples;
|
||||
int numBytes;
|
||||
SAMPLE max, val;
|
||||
double average;
|
||||
|
||||
printf("patest_record.c\n"); fflush(stdout);
|
||||
|
||||
data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */
|
||||
data.frameIndex = 0;
|
||||
numSamples = totalFrames * NUM_CHANNELS;
|
||||
numBytes = numSamples * sizeof(SAMPLE);
|
||||
data.recordedSamples = (SAMPLE *) malloc( numBytes ); /* From now on, recordedSamples is initialised. */
|
||||
if( data.recordedSamples == NULL )
|
||||
{
|
||||
printf("Could not allocate record array.\n");
|
||||
goto done;
|
||||
}
|
||||
for( i=0; i<numSamples; i++ ) data.recordedSamples[i] = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
inputParameters.channelCount = 2; /* stereo input */
|
||||
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* Record some audio. -------------------------------------------- */
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
NULL, /* &outputParameters, */
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
recordCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
printf("Now recording!!\n"); fflush(stdout);
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
{
|
||||
Pa_Sleep(1000);
|
||||
printf("index = %d\n", data.frameIndex ); fflush(stdout);
|
||||
}
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
/* Measure maximum peak amplitude. */
|
||||
max = 0;
|
||||
average = 0.0;
|
||||
for( i=0; i<numSamples; i++ )
|
||||
{
|
||||
val = data.recordedSamples[i];
|
||||
if( val < 0 ) val = -val; /* ABS */
|
||||
if( val > max )
|
||||
{
|
||||
max = val;
|
||||
}
|
||||
average += val;
|
||||
}
|
||||
|
||||
average = average / (double)numSamples;
|
||||
|
||||
printf("sample max amplitude = "PRINTF_S_FORMAT"\n", max );
|
||||
printf("sample average = %lf\n", average );
|
||||
|
||||
/* Write recorded data to a file. */
|
||||
#if 0
|
||||
{
|
||||
FILE *fid;
|
||||
fid = fopen("recorded.raw", "wb");
|
||||
if( fid == NULL )
|
||||
{
|
||||
printf("Could not open file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
|
||||
fclose( fid );
|
||||
printf("Wrote data to 'recorded.raw'\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Playback recorded data. -------------------------------------------- */
|
||||
data.frameIndex = 0;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
printf("Begin playback.\n"); fflush(stdout);
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
playCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
if( stream )
|
||||
{
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
printf("Waiting for playback to finish.\n"); fflush(stdout);
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
printf("Done.\n"); fflush(stdout);
|
||||
}
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
if( data.recordedSamples ) /* Sure it is NULL or valid. */
|
||||
free( data.recordedSamples );
|
||||
if( err != paNoError )
|
||||
{
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
err = 1; /* Always return 0 or 1, but no other return codes. */
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
/** @file patest_ringmix.c
|
||||
@brief Ring modulate inputs to left output, mix inputs to right output.
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "stdio.h"
|
||||
#include "portaudio.h"
|
||||
/* This will be called asynchronously by the PortAudio engine. */
|
||||
static int myCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
const float *in = (const float *) inputBuffer;
|
||||
float *out = (float *) outputBuffer;
|
||||
float leftInput, rightInput;
|
||||
unsigned int i;
|
||||
|
||||
/* Read input buffer, process data, and fill output buffer. */
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
leftInput = *in++; /* Get interleaved samples from input buffer. */
|
||||
rightInput = *in++;
|
||||
*out++ = leftInput * rightInput; /* ring modulation */
|
||||
*out++ = 0.5f * (leftInput + rightInput); /* mix */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open a PortAudioStream to input and output audio data. */
|
||||
int main(void)
|
||||
{
|
||||
PaStream *stream;
|
||||
Pa_Initialize();
|
||||
Pa_OpenDefaultStream(
|
||||
&stream,
|
||||
2, 2, /* stereo input and output */
|
||||
paFloat32, 44100.0,
|
||||
64, /* 64 frames per buffer */
|
||||
myCallback, NULL );
|
||||
Pa_StartStream( stream );
|
||||
Pa_Sleep( 10000 ); /* Sleep for 10 seconds while processing. */
|
||||
Pa_StopStream( stream );
|
||||
Pa_CloseStream( stream );
|
||||
Pa_Terminate();
|
||||
return 0;
|
||||
}
|
||||
@ -1,125 +0,0 @@
|
||||
/** @file patest_saw.c
|
||||
@brief Play a simple (aliasing) sawtooth wave.
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#define NUM_SECONDS (4)
|
||||
#define SAMPLE_RATE (44100)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float left_phase;
|
||||
float right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
/* Cast data passed through stream to our structure. */
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned int i;
|
||||
(void) inputBuffer; /* Prevent unused variable warning. */
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->left_phase; /* left */
|
||||
*out++ = data->right_phase; /* right */
|
||||
/* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
|
||||
data->left_phase += 0.01f;
|
||||
/* When signal reaches top, drop back down. */
|
||||
if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;
|
||||
/* higher pitch so we can distinguish left and right. */
|
||||
data->right_phase += 0.03f;
|
||||
if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
static paTestData data;
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
|
||||
printf("PortAudio Test: output sawtooth wave.\n");
|
||||
/* Initialize our data for use by callback. */
|
||||
data.left_phase = data.right_phase = 0.0;
|
||||
/* Initialize library before making any other calls. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Open an audio I/O stream. */
|
||||
err = Pa_OpenDefaultStream( &stream,
|
||||
0, /* no input channels */
|
||||
2, /* stereo output */
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
SAMPLE_RATE,
|
||||
256, /* frames per buffer */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Sleep for several seconds. */
|
||||
Pa_Sleep(NUM_SECONDS*1000);
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,151 +0,0 @@
|
||||
/** @file patest_sine.c
|
||||
@brief Play a sine wave for several seconds.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (5)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
|
||||
(void) timeInfo; /* Prevent unused variable warnings. */
|
||||
(void) statusFlags;
|
||||
(void) inputBuffer;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.left_phase = data.right_phase = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS );
|
||||
Pa_Sleep( NUM_SECONDS * 1000 );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,212 +0,0 @@
|
||||
/** @file patest_sine8.c
|
||||
@brief Test 8 bit data: play a sine wave for several seconds.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (8)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define TABLE_SIZE (200)
|
||||
#define TEST_UNSIGNED (0)
|
||||
|
||||
#if TEST_UNSIGNED
|
||||
#define TEST_FORMAT paUInt8
|
||||
#else
|
||||
#define TEST_FORMAT paInt8
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if TEST_UNSIGNED
|
||||
unsigned char sine[TABLE_SIZE];
|
||||
#else
|
||||
char sine[TABLE_SIZE];
|
||||
#endif
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
unsigned int framesToGo;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
char *out = (char*)outputBuffer;
|
||||
int i;
|
||||
int framesToCalc;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
|
||||
if( data->framesToGo < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = data->framesToGo;
|
||||
data->framesToGo = 0;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
data->framesToGo -= framesPerBuffer;
|
||||
}
|
||||
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<(int)framesPerBuffer; i++ )
|
||||
{
|
||||
#if TEST_UNSIGNED
|
||||
*out++ = (unsigned char) 0x80; /* left */
|
||||
*out++ = (unsigned char) 0x80; /* right */
|
||||
#else
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
#endif
|
||||
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream* stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
PaTime streamOpened;
|
||||
int i, totalSamps;
|
||||
|
||||
#if TEST_UNSIGNED
|
||||
printf("PortAudio Test: output UNsigned 8 bit sine wave.\n");
|
||||
#else
|
||||
printf("PortAudio Test: output signed 8 bit sine wave.\n");
|
||||
#endif
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (char) (127.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
|
||||
#if TEST_UNSIGNED
|
||||
data.sine[i] += (unsigned char) 0x80;
|
||||
#endif
|
||||
}
|
||||
data.left_phase = data.right_phase = 0;
|
||||
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
|
||||
outputParameters.channelCount = 2; /* Stereo output. */
|
||||
outputParameters.sampleFormat = TEST_FORMAT;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
err = Pa_OpenStream( &stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
256, /* Frames per buffer. */
|
||||
paClipOff, /* We won't output out of range samples so don't bother clipping them. */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
streamOpened = Pa_GetStreamTime( stream ); /* Time in seconds when stream was opened (approx). */
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
/* Watch until sound is halfway finished. */
|
||||
/* (Was ( Pa_StreamTime( stream ) < (totalSamps/2) ) in V18. */
|
||||
while( (Pa_GetStreamTime( stream ) - streamOpened) < (PaTime)NUM_SECONDS / 2.0 )
|
||||
Pa_Sleep(10);
|
||||
|
||||
/* Stop sound until ENTER hit. (Hu? don't see any keyboard-input here.) */
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
printf("Pause for 2 seconds.\n");
|
||||
Pa_Sleep( 2000 );
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
printf("Waiting for sound to finish.\n");
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
Pa_Sleep(100);
|
||||
if( err < 0 )
|
||||
goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError )
|
||||
goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,196 +0,0 @@
|
||||
/** @file patest_sine_formats.c
|
||||
@brief Play a sine wave for several seconds. Test various data formats.
|
||||
@author Phil Burk
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (10)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (512)
|
||||
#define LEFT_FREQ (SAMPLE_RATE/256.0) /* So we hit 1.0 */
|
||||
#define RIGHT_FREQ (500.0)
|
||||
#define AMPLITUDE (1.0)
|
||||
|
||||
/* Select ONE format for testing. */
|
||||
#define TEST_UINT8 (0)
|
||||
#define TEST_INT8 (0)
|
||||
#define TEST_INT16 (1)
|
||||
#define TEST_FLOAT32 (0)
|
||||
|
||||
#if TEST_UINT8
|
||||
#define TEST_FORMAT paUInt8
|
||||
typedef unsigned char SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0x80)
|
||||
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
|
||||
#define FORMAT_NAME "Unsigned 8 Bit"
|
||||
|
||||
#elif TEST_INT8
|
||||
#define TEST_FORMAT paInt8
|
||||
typedef char SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0)
|
||||
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
|
||||
#define FORMAT_NAME "Signed 8 Bit"
|
||||
|
||||
#elif TEST_INT16
|
||||
#define TEST_FORMAT paInt16
|
||||
typedef short SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0)
|
||||
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(32767 * (x)))
|
||||
#define FORMAT_NAME "Signed 16 Bit"
|
||||
|
||||
#elif TEST_FLOAT32
|
||||
#define TEST_FORMAT paFloat32
|
||||
typedef float SAMPLE_t;
|
||||
#define SAMPLE_ZERO (0.0)
|
||||
#define DOUBLE_TO_SAMPLE(x) ((SAMPLE_t)(x))
|
||||
#define FORMAT_NAME "Float 32 Bit"
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double left_phase;
|
||||
double right_phase;
|
||||
unsigned int framesToGo;
|
||||
}
|
||||
paTestData;
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer,
|
||||
void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
SAMPLE_t *out = (SAMPLE_t *)outputBuffer;
|
||||
int i;
|
||||
int framesToCalc;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
|
||||
if( data->framesToGo < framesPerBuffer )
|
||||
{
|
||||
framesToCalc = data->framesToGo;
|
||||
data->framesToGo = 0;
|
||||
finished = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesToCalc = framesPerBuffer;
|
||||
data->framesToGo -= framesPerBuffer;
|
||||
}
|
||||
|
||||
for( i=0; i<framesToCalc; i++ )
|
||||
{
|
||||
data->left_phase += (LEFT_FREQ / SAMPLE_RATE);
|
||||
if( data->left_phase > 1.0) data->left_phase -= 1.0;
|
||||
*out++ = DOUBLE_TO_SAMPLE( AMPLITUDE * sin( (data->left_phase * M_PI * 2. )));
|
||||
|
||||
data->right_phase += (RIGHT_FREQ / SAMPLE_RATE);
|
||||
if( data->right_phase > 1.0) data->right_phase -= 1.0;
|
||||
*out++ = DOUBLE_TO_SAMPLE( AMPLITUDE * sin( (data->right_phase * M_PI * 2. )));
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<(int)framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = SAMPLE_ZERO; /* left */
|
||||
*out++ = SAMPLE_ZERO; /* right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream *stream;
|
||||
PaStreamParameters outputParameters;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int totalSamps;
|
||||
|
||||
printf("PortAudio Test: output " FORMAT_NAME "\n");
|
||||
|
||||
data.left_phase = data.right_phase = 0.0;
|
||||
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
|
||||
outputParameters.channelCount = 2; /* Stereo output */
|
||||
outputParameters.sampleFormat = TEST_FORMAT; /* Selected above. */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
err = Pa_OpenStream( &stream,
|
||||
NULL, /* No input. */
|
||||
&outputParameters, /* As above. */
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Waiting %d seconds for sound to finish.\n", NUM_SECONDS );
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
|
||||
if( err < 0 ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
|
||||
printf("PortAudio Test Finished: " FORMAT_NAME "\n");
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,208 +0,0 @@
|
||||
/** @file patest_sine_time.c
|
||||
@brief Play a sine wave for several seconds, pausing in the middle.
|
||||
Uses the Pa_GetStreamTime() call.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "portaudio.h"
|
||||
#include "pa_util.h"
|
||||
|
||||
#define NUM_SECONDS (8)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (64)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double left_phase;
|
||||
double right_phase;
|
||||
volatile PaTime outTime;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned int i;
|
||||
|
||||
double left_phaseInc = 0.02;
|
||||
double right_phaseInc = 0.06;
|
||||
|
||||
double left_phase = data->left_phase;
|
||||
double right_phase = data->right_phase;
|
||||
|
||||
(void) statusFlags; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
data->outTime = timeInfo->outputBufferDacTime;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
left_phase += left_phaseInc;
|
||||
if( left_phase > TWOPI ) left_phase -= TWOPI;
|
||||
*out++ = (float) sin( left_phase );
|
||||
|
||||
right_phase += right_phaseInc;
|
||||
if( right_phase > TWOPI ) right_phase -= TWOPI;
|
||||
*out++ = (float) sin( right_phase );
|
||||
}
|
||||
|
||||
data->left_phase = left_phase;
|
||||
data->right_phase = right_phase;
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
static void ReportStreamTime( PaStream *stream, paTestData *data );
|
||||
static void ReportStreamTime( PaStream *stream, paTestData *data )
|
||||
{
|
||||
PaTime streamTime, latency, outTime;
|
||||
|
||||
streamTime = Pa_GetStreamTime( stream );
|
||||
outTime = data->outTime;
|
||||
if( outTime < 0.0 )
|
||||
{
|
||||
printf("Stream time = %8.1f\n", streamTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
latency = outTime - streamTime;
|
||||
printf("Stream time = %8.4f, outTime = %8.4f, latency = %8.4f\n",
|
||||
streamTime, outTime, latency );
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
PaTime startTime;
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
|
||||
data.left_phase = data.right_phase = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Watch until sound is halfway finished. */
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS/2 ); fflush(stdout);
|
||||
|
||||
data.outTime = -1.0; /* mark time for callback as undefined */
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
startTime = Pa_GetStreamTime( stream );
|
||||
|
||||
do
|
||||
{
|
||||
ReportStreamTime( stream, &data );
|
||||
Pa_Sleep(100);
|
||||
} while( (Pa_GetStreamTime( stream ) - startTime) < (NUM_SECONDS/2) );
|
||||
|
||||
/* Stop sound for 2 seconds. */
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Pause for 2 seconds.\n"); fflush(stdout);
|
||||
Pa_Sleep( 2000 );
|
||||
|
||||
data.outTime = -1.0; /* mark time for callback as undefined */
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
startTime = Pa_GetStreamTime( stream );
|
||||
|
||||
printf("Play until sound is finished.\n"); fflush(stdout);
|
||||
do
|
||||
{
|
||||
ReportStreamTime( stream, &data );
|
||||
Pa_Sleep(100);
|
||||
} while( (Pa_GetStreamTime( stream ) - startTime) < (NUM_SECONDS/2) );
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,162 +0,0 @@
|
||||
/** @file patest_start_stop.c
|
||||
@brief Play a sine wave for several seconds
|
||||
- start and stop the stream multiple times.
|
||||
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define OUTPUT_DEVICE Pa_GetDefaultOutputDevice() /* default output device */
|
||||
|
||||
#define NUM_SECONDS (3)
|
||||
#define NUM_LOOPS (4)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (400)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
|
||||
(void) timeInfo; /* Prevent unused variable warnings. */
|
||||
(void) statusFlags;
|
||||
(void) inputBuffer;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.left_phase = data.right_phase = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = OUTPUT_DEVICE;
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
for( i=0; i<NUM_LOOPS; i++ )
|
||||
{
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS );
|
||||
Pa_Sleep( NUM_SECONDS * 1000 );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Stopped.\n" );
|
||||
Pa_Sleep( 1000 );
|
||||
}
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,313 +0,0 @@
|
||||
/** @file patest_stop.c
|
||||
@brief Test different ways of stopping audio.
|
||||
|
||||
Test the three ways of stopping audio:
|
||||
- calling Pa_StopStream(),
|
||||
- calling Pa_AbortStream(),
|
||||
- and returning a 1 from the callback function.
|
||||
|
||||
A long latency is set up so that you can hear the difference.
|
||||
Then a simple 8 note sequence is repeated twice.
|
||||
The program will print what you should hear.
|
||||
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
|
||||
#define SLEEP_DUR (200)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define LATENCY_SECONDS (3.f)
|
||||
#define FRAMES_PER_NOTE (SAMPLE_RATE/2)
|
||||
#define MAX_REPEATS (2)
|
||||
#define FUNDAMENTAL (400.0f / SAMPLE_RATE)
|
||||
#define NOTE_0 (FUNDAMENTAL * 1.0f / 1.0f)
|
||||
#define NOTE_1 (FUNDAMENTAL * 5.0f / 4.0f)
|
||||
#define NOTE_2 (FUNDAMENTAL * 4.0f / 3.0f)
|
||||
#define NOTE_3 (FUNDAMENTAL * 3.0f / 2.0f)
|
||||
#define NOTE_4 (FUNDAMENTAL * 2.0f / 1.0f)
|
||||
#define MODE_FINISH (0)
|
||||
#define MODE_STOP (1)
|
||||
#define MODE_ABORT (2)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TABLE_SIZE (400)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float waveform[TABLE_SIZE + 1]; /* Add one for guard point for interpolation. */
|
||||
float phase_increment;
|
||||
float phase;
|
||||
float *tune;
|
||||
int notesPerTune;
|
||||
int frameCounter;
|
||||
int noteCounter;
|
||||
int repeatCounter;
|
||||
PaTime outTime;
|
||||
int stopMode;
|
||||
int done;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/************* Prototypes *****************************/
|
||||
int TestStopMode( paTestData *data );
|
||||
float LookupWaveform( paTestData *data, float phase );
|
||||
|
||||
/******************************************************
|
||||
* Convert phase between 0.0 and 1.0 to waveform value
|
||||
* using linear interpolation.
|
||||
*/
|
||||
float LookupWaveform( paTestData *data, float phase )
|
||||
{
|
||||
float fIndex = phase*TABLE_SIZE;
|
||||
int index = (int) fIndex;
|
||||
float fract = fIndex - index;
|
||||
float lo = data->waveform[index];
|
||||
float hi = data->waveform[index+1];
|
||||
float val = lo + fract*(hi-lo);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
float value;
|
||||
unsigned int i = 0;
|
||||
int finished = paContinue;
|
||||
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
|
||||
/* data->outTime = outTime; */
|
||||
|
||||
if( !data->done )
|
||||
{
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
/* Are we done with this note? */
|
||||
if( data->frameCounter >= FRAMES_PER_NOTE )
|
||||
{
|
||||
data->noteCounter += 1;
|
||||
data->frameCounter = 0;
|
||||
/* Are we done with this tune? */
|
||||
if( data->noteCounter >= data->notesPerTune )
|
||||
{
|
||||
data->noteCounter = 0;
|
||||
data->repeatCounter += 1;
|
||||
/* Are we totally done? */
|
||||
if( data->repeatCounter >= MAX_REPEATS )
|
||||
{
|
||||
data->done = 1;
|
||||
if( data->stopMode == MODE_FINISH )
|
||||
{
|
||||
finished = paComplete;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
data->phase_increment = data->tune[data->noteCounter];
|
||||
}
|
||||
value = LookupWaveform(data, data->phase);
|
||||
*out++ = value; /* left */
|
||||
*out++ = value; /* right */
|
||||
data->phase += data->phase_increment;
|
||||
if( data->phase >= 1.0f ) data->phase -= 1.0f;
|
||||
|
||||
data->frameCounter += 1;
|
||||
}
|
||||
}
|
||||
/* zero remainder of final buffer */
|
||||
for( ; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = 0; /* left */
|
||||
*out++ = 0; /* right */
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
paTestData data;
|
||||
int i;
|
||||
float simpleTune[] = { NOTE_0, NOTE_1, NOTE_2, NOTE_3, NOTE_4, NOTE_3, NOTE_2, NOTE_1 };
|
||||
|
||||
printf("PortAudio Test: play song and test stopping. ask for %f seconds latency\n", LATENCY_SECONDS );
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.waveform[i] = (float) (
|
||||
(0.2 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. )) +
|
||||
(0.2 * sin( ((double)(3*i)/(double)TABLE_SIZE) * M_PI * 2. )) +
|
||||
(0.1 * sin( ((double)(5*i)/(double)TABLE_SIZE) * M_PI * 2. ))
|
||||
);
|
||||
}
|
||||
data.waveform[TABLE_SIZE] = data.waveform[0]; /* Set guard point. */
|
||||
data.tune = &simpleTune[0];
|
||||
data.notesPerTune = sizeof(simpleTune) / sizeof(float);
|
||||
|
||||
printf("Test MODE_FINISH - callback returns 1.\n");
|
||||
printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
|
||||
data.stopMode = MODE_FINISH;
|
||||
if( TestStopMode( &data ) != paNoError )
|
||||
{
|
||||
printf("Test of MODE_FINISH failed!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("Test MODE_STOP - stop when song is done.\n");
|
||||
printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
|
||||
data.stopMode = MODE_STOP;
|
||||
if( TestStopMode( &data ) != paNoError )
|
||||
{
|
||||
printf("Test of MODE_STOP failed!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf("Test MODE_ABORT - abort immediately.\n");
|
||||
printf("Should hear last repetition cut short by %f seconds.\n", LATENCY_SECONDS);
|
||||
data.stopMode = MODE_ABORT;
|
||||
if( TestStopMode( &data ) != paNoError )
|
||||
{
|
||||
printf("Test of MODE_ABORT failed!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TestStopMode( paTestData *data )
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
|
||||
data->done = 0;
|
||||
data->phase = 0.0;
|
||||
data->frameCounter = 0;
|
||||
data->noteCounter = 0;
|
||||
data->repeatCounter = 0;
|
||||
data->phase_increment = data->tune[data->noteCounter];
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = OUTPUT_DEVICE;
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = LATENCY_SECONDS;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
if( data->stopMode == MODE_FINISH )
|
||||
{
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
{
|
||||
/*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
|
||||
data->noteCounter, data->repeatCounter );
|
||||
fflush(stdout); */
|
||||
Pa_Sleep( SLEEP_DUR );
|
||||
}
|
||||
if( err < 0 ) goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
while( data->repeatCounter < MAX_REPEATS )
|
||||
{
|
||||
/*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
|
||||
data->noteCounter, data->repeatCounter );
|
||||
fflush(stdout); */
|
||||
Pa_Sleep( SLEEP_DUR );
|
||||
}
|
||||
}
|
||||
|
||||
if( data->stopMode == MODE_ABORT )
|
||||
{
|
||||
printf("Call Pa_AbortStream()\n");
|
||||
err = Pa_AbortStream( stream );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Call Pa_StopStream()\n");
|
||||
err = Pa_StopStream( stream );
|
||||
}
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Call Pa_CloseStream()\n"); fflush(stdout);
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
|
||||
return err;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,432 +0,0 @@
|
||||
/** @file patest_stop_playout.c
|
||||
@brief Test whether all queued samples are played when Pa_StopStream()
|
||||
is used with a callback or read/write stream, or when the callback
|
||||
returns paComplete.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com/
|
||||
* Copyright (c) 1999-2004 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (1024)
|
||||
|
||||
#define TONE_SECONDS (1) /* long tone */
|
||||
#define TONE_FADE_SECONDS (.04) /* fades at start and end of long tone */
|
||||
#define GAP_SECONDS (.25) /* gap between long tone and blip */
|
||||
#define BLIP_SECONDS (.035) /* short blip */
|
||||
|
||||
#define NUM_REPEATS (3)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (2048)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE+1];
|
||||
|
||||
int repeatCount;
|
||||
|
||||
double phase;
|
||||
double lowIncrement, highIncrement;
|
||||
|
||||
int gap1Length, toneLength, toneFadesLength, gap2Length, blipLength;
|
||||
int gap1Countdown, toneCountdown, gap2Countdown, blipCountdown;
|
||||
}
|
||||
TestData;
|
||||
|
||||
|
||||
static void RetriggerTestSignalGenerator( TestData *data )
|
||||
{
|
||||
data->phase = 0.;
|
||||
data->gap1Countdown = data->gap1Length;
|
||||
data->toneCountdown = data->toneLength;
|
||||
data->gap2Countdown = data->gap2Length;
|
||||
data->blipCountdown = data->blipLength;
|
||||
}
|
||||
|
||||
|
||||
static void ResetTestSignalGenerator( TestData *data )
|
||||
{
|
||||
data->repeatCount = 0;
|
||||
RetriggerTestSignalGenerator( data );
|
||||
}
|
||||
|
||||
|
||||
static void InitTestSignalGenerator( TestData *data )
|
||||
{
|
||||
int signalLengthModBufferLength, i;
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data->sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data->sine[TABLE_SIZE] = data->sine[0]; /* guard point for linear interpolation */
|
||||
|
||||
|
||||
|
||||
data->lowIncrement = (330. / SAMPLE_RATE) * TABLE_SIZE;
|
||||
data->highIncrement = (1760. / SAMPLE_RATE) * TABLE_SIZE;
|
||||
|
||||
data->gap1Length = GAP_SECONDS * SAMPLE_RATE;
|
||||
data->toneLength = TONE_SECONDS * SAMPLE_RATE;
|
||||
data->toneFadesLength = TONE_FADE_SECONDS * SAMPLE_RATE;
|
||||
data->gap2Length = GAP_SECONDS * SAMPLE_RATE;
|
||||
data->blipLength = BLIP_SECONDS * SAMPLE_RATE;
|
||||
|
||||
/* adjust signal length to be a multiple of the buffer length */
|
||||
signalLengthModBufferLength = (data->gap1Length + data->toneLength + data->gap2Length + data->blipLength) % FRAMES_PER_BUFFER;
|
||||
if( signalLengthModBufferLength > 0 )
|
||||
data->toneLength += signalLengthModBufferLength;
|
||||
|
||||
ResetTestSignalGenerator( data );
|
||||
}
|
||||
|
||||
|
||||
#define MIN( a, b ) (((a)<(b))?(a):(b))
|
||||
|
||||
static void GenerateTestSignal( TestData *data, float *stereo, int frameCount )
|
||||
{
|
||||
int framesGenerated = 0;
|
||||
float output;
|
||||
long index;
|
||||
float fraction;
|
||||
int count, i;
|
||||
|
||||
while( framesGenerated < frameCount && data->repeatCount < NUM_REPEATS )
|
||||
{
|
||||
if( framesGenerated < frameCount && data->gap1Countdown > 0 ){
|
||||
count = MIN( frameCount - framesGenerated, data->gap1Countdown );
|
||||
for( i=0; i < count; ++i )
|
||||
{
|
||||
*stereo++ = 0.f;
|
||||
*stereo++ = 0.f;
|
||||
}
|
||||
|
||||
data->gap1Countdown -= count;
|
||||
framesGenerated += count;
|
||||
}
|
||||
|
||||
if( framesGenerated < frameCount && data->toneCountdown > 0 ){
|
||||
count = MIN( frameCount - framesGenerated, data->toneCountdown );
|
||||
for( i=0; i < count; ++i )
|
||||
{
|
||||
/* tone with data->lowIncrement phase increment */
|
||||
index = (long)data->phase;
|
||||
fraction = data->phase - index;
|
||||
output = data->sine[ index ] + (data->sine[ index + 1 ] - data->sine[ index ]) * fraction;
|
||||
|
||||
data->phase += data->lowIncrement;
|
||||
while( data->phase >= TABLE_SIZE )
|
||||
data->phase -= TABLE_SIZE;
|
||||
|
||||
/* apply fade to ends */
|
||||
|
||||
if( data->toneCountdown < data->toneFadesLength )
|
||||
{
|
||||
/* cosine-bell fade out at end */
|
||||
output *= (-cos(((float)data->toneCountdown / (float)data->toneFadesLength) * M_PI) + 1.) * .5;
|
||||
}
|
||||
else if( data->toneCountdown > data->toneLength - data->toneFadesLength )
|
||||
{
|
||||
/* cosine-bell fade in at start */
|
||||
output *= (cos(((float)(data->toneCountdown - (data->toneLength - data->toneFadesLength)) / (float)data->toneFadesLength) * M_PI) + 1.) * .5;
|
||||
}
|
||||
|
||||
output *= .5; /* play tone half as loud as blip */
|
||||
|
||||
*stereo++ = output;
|
||||
*stereo++ = output;
|
||||
|
||||
data->toneCountdown--;
|
||||
}
|
||||
|
||||
framesGenerated += count;
|
||||
}
|
||||
|
||||
if( framesGenerated < frameCount && data->gap2Countdown > 0 ){
|
||||
count = MIN( frameCount - framesGenerated, data->gap2Countdown );
|
||||
for( i=0; i < count; ++i )
|
||||
{
|
||||
*stereo++ = 0.f;
|
||||
*stereo++ = 0.f;
|
||||
}
|
||||
|
||||
data->gap2Countdown -= count;
|
||||
framesGenerated += count;
|
||||
}
|
||||
|
||||
if( framesGenerated < frameCount && data->blipCountdown > 0 ){
|
||||
count = MIN( frameCount - framesGenerated, data->blipCountdown );
|
||||
for( i=0; i < count; ++i )
|
||||
{
|
||||
/* tone with data->highIncrement phase increment */
|
||||
index = (long)data->phase;
|
||||
fraction = data->phase - index;
|
||||
output = data->sine[ index ] + (data->sine[ index + 1 ] - data->sine[ index ]) * fraction;
|
||||
|
||||
data->phase += data->highIncrement;
|
||||
while( data->phase >= TABLE_SIZE )
|
||||
data->phase -= TABLE_SIZE;
|
||||
|
||||
/* cosine-bell envelope over whole blip */
|
||||
output *= (-cos( ((float)data->blipCountdown / (float)data->blipLength) * 2. * M_PI) + 1.) * .5;
|
||||
|
||||
*stereo++ = output;
|
||||
*stereo++ = output;
|
||||
|
||||
data->blipCountdown--;
|
||||
}
|
||||
|
||||
framesGenerated += count;
|
||||
}
|
||||
|
||||
|
||||
if( data->blipCountdown == 0 )
|
||||
{
|
||||
RetriggerTestSignalGenerator( data );
|
||||
data->repeatCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if( framesGenerated < frameCount )
|
||||
{
|
||||
count = frameCount - framesGenerated;
|
||||
for( i=0; i < count; ++i )
|
||||
{
|
||||
*stereo++ = 0.f;
|
||||
*stereo++ = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int IsTestSignalFinished( TestData *data )
|
||||
{
|
||||
if( data->repeatCount >= NUM_REPEATS )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int TestCallback1( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long frameCount,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
GenerateTestSignal( (TestData*)userData, (float*)outputBuffer, frameCount );
|
||||
|
||||
if( IsTestSignalFinished( (TestData*)userData ) )
|
||||
return paComplete;
|
||||
else
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
|
||||
volatile int testCallback2Finished = 0;
|
||||
|
||||
static int TestCallback2( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long frameCount,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
GenerateTestSignal( (TestData*)userData, (float*)outputBuffer, frameCount );
|
||||
|
||||
if( IsTestSignalFinished( (TestData*)userData ) )
|
||||
testCallback2Finished = 1;
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
TestData data;
|
||||
float writeBuffer[ FRAMES_PER_BUFFER * 2 ];
|
||||
|
||||
printf("PortAudio Test: check that stopping stream plays out all queued samples. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
|
||||
InitTestSignalGenerator( &data );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* test paComplete ---------------------------------------------------------- */
|
||||
|
||||
ResetTestSignalGenerator( &data );
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
TestCallback1,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
printf("\nPlaying 'tone-blip' %d times using callback, stops by returning paComplete from callback.\n", NUM_REPEATS );
|
||||
printf("If final blip is not intact, callback+paComplete implementation may be faulty.\n\n" );
|
||||
|
||||
while( (err = Pa_IsStreamActive( stream )) == 1 )
|
||||
Pa_Sleep( 5 );
|
||||
|
||||
if( err != 0 ) goto error;
|
||||
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Sleep( 500 );
|
||||
|
||||
/* test Pa_StopStream() with callback --------------------------------------- */
|
||||
|
||||
ResetTestSignalGenerator( &data );
|
||||
|
||||
testCallback2Finished = 0;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
TestCallback2,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
printf("\nPlaying 'tone-blip' %d times using callback, stops by calling Pa_StopStream.\n", NUM_REPEATS );
|
||||
printf("If final blip is not intact, callback+Pa_StopStream implementation may be faulty.\n\n" );
|
||||
|
||||
/* note that polling a volatile flag is not a good way to synchronise with
|
||||
the callback, but it's the best we can do portably. */
|
||||
while( !testCallback2Finished )
|
||||
Pa_Sleep( 2 );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Sleep( 500 );
|
||||
|
||||
/* test Pa_StopStream() with Pa_WriteStream --------------------------------- */
|
||||
|
||||
ResetTestSignalGenerator( &data );
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
NULL, /* no callback, use blocking API */
|
||||
NULL ); /* no callback, so no callback userData */
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
printf("\nPlaying 'tone-blip' %d times using Pa_WriteStream, stops by calling Pa_StopStream.\n", NUM_REPEATS );
|
||||
printf("If final blip is not intact, Pa_WriteStream+Pa_StopStream implementation may be faulty.\n\n" );
|
||||
|
||||
do{
|
||||
GenerateTestSignal( &data, writeBuffer, FRAMES_PER_BUFFER );
|
||||
err = Pa_WriteStream( stream, writeBuffer, FRAMES_PER_BUFFER );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
}while( !IsTestSignalFinished( &data ) );
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
|
||||
return err;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,259 +0,0 @@
|
||||
/** @file patest_sync.c
|
||||
@brief Test time stamping and synchronization of audio and video.
|
||||
|
||||
A high latency is used so we can hear the difference in time.
|
||||
Random durations are used so we know we are hearing the right beep
|
||||
and not the one before or after.
|
||||
|
||||
Sequence of events:
|
||||
-# Foreground requests a beep.
|
||||
-# Background randomly schedules a beep.
|
||||
-# Foreground waits for the beep to be heard based on PaUtil_GetTime().
|
||||
-# Foreground outputs video (printf) in sync with audio.
|
||||
-# Repeat.
|
||||
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
#include "pa_util.h"
|
||||
#define NUM_BEEPS (6)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define SAMPLE_PERIOD (1.0/44100.0)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define BEEP_DURATION (400)
|
||||
#define LATENCY_MSEC (2000)
|
||||
#define SLEEP_MSEC (10)
|
||||
#define TIMEOUT_MSEC (15000)
|
||||
|
||||
#define STATE_BKG_IDLE (0)
|
||||
#define STATE_BKG_PENDING (1)
|
||||
#define STATE_BKG_BEEPING (2)
|
||||
typedef struct
|
||||
{
|
||||
float left_phase;
|
||||
float right_phase;
|
||||
int state;
|
||||
int requestBeep; /* Set by foreground, cleared by background. */
|
||||
PaTime beepTime;
|
||||
int beepCount;
|
||||
double latency; /* For debugging. */
|
||||
}
|
||||
paTestData;
|
||||
|
||||
static unsigned long GenerateRandomNumber( void );
|
||||
/************************************************************/
|
||||
/* Calculate pseudo-random 32 bit number based on linear congruential method. */
|
||||
static unsigned long GenerateRandomNumber( void )
|
||||
{
|
||||
static unsigned long randSeed = 99887766; /* Change this for different random sequences. */
|
||||
randSeed = (randSeed * 196314165) + 907633515;
|
||||
return randSeed;
|
||||
}
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo *timeInfo,
|
||||
PaStreamCallbackFlags statusFlags, void *userData )
|
||||
{
|
||||
/* Cast data passed through stream to our structure. */
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned int i;
|
||||
(void) inputBuffer;
|
||||
|
||||
data->latency = timeInfo->outputBufferDacTime - timeInfo->currentTime;
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
switch( data->state )
|
||||
{
|
||||
case STATE_BKG_IDLE:
|
||||
/* Schedule beep at some random time in the future. */
|
||||
if( data->requestBeep )
|
||||
{
|
||||
int random = GenerateRandomNumber() >> 14;
|
||||
data->beepTime = timeInfo->outputBufferDacTime + (( (double)(random + SAMPLE_RATE)) * SAMPLE_PERIOD );
|
||||
data->state = STATE_BKG_PENDING;
|
||||
}
|
||||
*out++ = 0.0; /* left */
|
||||
*out++ = 0.0; /* right */
|
||||
break;
|
||||
|
||||
case STATE_BKG_PENDING:
|
||||
if( (timeInfo->outputBufferDacTime + (i*SAMPLE_PERIOD)) >= data->beepTime )
|
||||
{
|
||||
data->state = STATE_BKG_BEEPING;
|
||||
data->beepCount = BEEP_DURATION;
|
||||
data->left_phase = data->right_phase = 0.0;
|
||||
}
|
||||
*out++ = 0.0; /* left */
|
||||
*out++ = 0.0; /* right */
|
||||
break;
|
||||
|
||||
case STATE_BKG_BEEPING:
|
||||
if( data->beepCount <= 0 )
|
||||
{
|
||||
data->state = STATE_BKG_IDLE;
|
||||
data->requestBeep = 0;
|
||||
*out++ = 0.0; /* left */
|
||||
*out++ = 0.0; /* right */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Play sawtooth wave. */
|
||||
*out++ = data->left_phase; /* left */
|
||||
*out++ = data->right_phase; /* right */
|
||||
/* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
|
||||
data->left_phase += 0.01f;
|
||||
/* When signal reaches top, drop back down. */
|
||||
if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;
|
||||
/* higher pitch so we can distinguish left and right. */
|
||||
data->right_phase += 0.03f;
|
||||
if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
|
||||
}
|
||||
data->beepCount -= 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
data->state = STATE_BKG_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData DATA;
|
||||
int i, timeout;
|
||||
PaTime previousTime;
|
||||
PaStreamParameters outputParameters;
|
||||
printf("PortAudio Test: you should see BEEP at the same time you hear it.\n");
|
||||
printf("Wait for a few seconds random delay between BEEPs.\n");
|
||||
printf("BEEP %d times.\n", NUM_BEEPS );
|
||||
/* Initialize our DATA for use by callback. */
|
||||
DATA.left_phase = DATA.right_phase = 0.0;
|
||||
DATA.state = STATE_BKG_IDLE;
|
||||
DATA.requestBeep = 0;
|
||||
/* Initialize library before making any other calls. */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice();
|
||||
outputParameters.channelCount = 2;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
outputParameters.sampleFormat = paFloat32;
|
||||
outputParameters.suggestedLatency = (double)LATENCY_MSEC / 1000;
|
||||
|
||||
/* Open an audio I/O stream. */
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&DATA );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("started\n");
|
||||
fflush(stdout);
|
||||
|
||||
previousTime = Pa_GetStreamTime( stream );
|
||||
for( i=0; i<NUM_BEEPS; i++ )
|
||||
{
|
||||
/* Request a beep from background. */
|
||||
DATA.requestBeep = 1;
|
||||
|
||||
/* Wait for background to acknowledge request. */
|
||||
timeout = TIMEOUT_MSEC;
|
||||
while( (DATA.requestBeep == 1) && (timeout-- > 0 ) ) Pa_Sleep(SLEEP_MSEC);
|
||||
if( timeout <= 0 )
|
||||
{
|
||||
fprintf( stderr, "Timed out waiting for background to acknowledge request.\n" );
|
||||
goto error;
|
||||
}
|
||||
printf("calc beep for %9.3f, latency = %6.3f\n", DATA.beepTime, DATA.latency );
|
||||
fflush(stdout);
|
||||
|
||||
/* Wait for scheduled beep time. */
|
||||
timeout = TIMEOUT_MSEC + (10000/SLEEP_MSEC);
|
||||
while( (Pa_GetStreamTime( stream ) < DATA.beepTime) && (timeout-- > 0 ) )
|
||||
{
|
||||
Pa_Sleep(SLEEP_MSEC);
|
||||
}
|
||||
if( timeout <= 0 )
|
||||
{
|
||||
fprintf( stderr, "Timed out waiting for time. Now = %9.3f, Beep for %9.3f.\n",
|
||||
PaUtil_GetTime(), DATA.beepTime );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Beep should be sounding now so print synchronized BEEP. */
|
||||
printf("hear \"BEEP\" at %9.3f, delta = %9.3f\n",
|
||||
Pa_GetStreamTime( stream ), (DATA.beepTime - previousTime) );
|
||||
fflush(stdout);
|
||||
|
||||
previousTime = DATA.beepTime;
|
||||
}
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,173 +0,0 @@
|
||||
/** @file patest_toomanysines.c
|
||||
@brief Play more sine waves than we can handle in real time as a stress test.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define MAX_SINES (500)
|
||||
#define MAX_LOAD (1.2)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (512)
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
#define TWOPI (M_PI * 2.0)
|
||||
|
||||
typedef struct paTestData
|
||||
{
|
||||
int numSines;
|
||||
double phases[MAX_SINES];
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int j;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent unused variable warning. */
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
float output = 0.0;
|
||||
double phaseInc = 0.02;
|
||||
double phase;
|
||||
for( j=0; j<data->numSines; j++ )
|
||||
{
|
||||
/* Advance phase of next oscillator. */
|
||||
phase = data->phases[j];
|
||||
phase += phaseInc;
|
||||
if( phase > TWOPI ) phase -= TWOPI;
|
||||
|
||||
phaseInc *= 1.02;
|
||||
if( phaseInc > 0.5 ) phaseInc *= 0.5;
|
||||
|
||||
/* This is not a very efficient way to calc sines. */
|
||||
output += (float) sin( phase );
|
||||
data->phases[j] = phase;
|
||||
}
|
||||
*out++ = (float) (output / data->numSines);
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
int numStress;
|
||||
paTestData data = {0};
|
||||
double load;
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
|
||||
SAMPLE_RATE, FRAMES_PER_BUFFER, MAX_LOAD );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 1; /* mono output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Determine number of sines required to get to 50% */
|
||||
do
|
||||
{
|
||||
data.numSines++;
|
||||
Pa_Sleep( 100 );
|
||||
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("numSines = %d, CPU load = %f\n", data.numSines, load );
|
||||
}
|
||||
while( load < 0.5 );
|
||||
|
||||
/* Calculate target stress value then ramp up to that level*/
|
||||
numStress = (int) (2.0 * data.numSines * MAX_LOAD );
|
||||
for( ; data.numSines < numStress; data.numSines++ )
|
||||
{
|
||||
Pa_Sleep( 200 );
|
||||
load = Pa_GetStreamCpuLoad( stream );
|
||||
printf("STRESSING: numSines = %d, CPU load = %f\n", data.numSines, load );
|
||||
}
|
||||
|
||||
printf("Suffer for 5 seconds.\n");
|
||||
Pa_Sleep( 5000 );
|
||||
|
||||
printf("Stop stream.\n");
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* patest_two_rates.c
|
||||
* Play two streams at different rates to make sure they don't interfere.
|
||||
*
|
||||
* Author: Phil Burk http://www.softsynth.com
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
|
||||
#define SAMPLE_RATE_1 (44100)
|
||||
#define SAMPLE_RATE_2 (44100)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define FREQ_INCR (0.1)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double phase;
|
||||
double numFrames;
|
||||
} paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
int frameIndex, channelIndex;
|
||||
int finished = 0;
|
||||
(void) outTime; /* Prevent unused variable warnings. */
|
||||
(void) inputBuffer;
|
||||
|
||||
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
|
||||
{
|
||||
/* Generate sine wave. */
|
||||
float value = (float) 0.3 * sin(data->phase);
|
||||
/* Stereo - two channels. */
|
||||
*out++ = value;
|
||||
*out++ = value;
|
||||
|
||||
data->phase += FREQ_INCR;
|
||||
if( data->phase >= (2.0 * M_PI) ) data->phase -= (2.0 * M_PI);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
PortAudioStream *stream1;
|
||||
PortAudioStream *stream2;
|
||||
paTestData data1 = {0};
|
||||
paTestData data2 = {0};
|
||||
printf("PortAudio Test: two rates.\n" );
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
/* Start first stream. **********************/
|
||||
err = Pa_OpenStream(
|
||||
&stream1,
|
||||
paNoDevice, /* default input device */
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
2, /* Stereo */
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE_1,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data1 );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream1 );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Sleep( 3 * 1000 );
|
||||
|
||||
/* Start second stream. **********************/
|
||||
err = Pa_OpenStream(
|
||||
&stream2,
|
||||
paNoDevice, /* default input device */
|
||||
0, /* no input */
|
||||
paFloat32, /* 32 bit floating point input */
|
||||
NULL,
|
||||
OUTPUT_DEVICE,
|
||||
2, /* Stereo */
|
||||
paFloat32, /* 32 bit floating point output */
|
||||
NULL,
|
||||
SAMPLE_RATE_2,
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data2 );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream2 );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Sleep( 3 * 1000 );
|
||||
|
||||
err = Pa_StopStream( stream2 );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Sleep( 3 * 1000 );
|
||||
|
||||
err = Pa_StopStream( stream1 );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_CloseStream( stream2 );
|
||||
Pa_CloseStream( stream1 );
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,151 +0,0 @@
|
||||
/** @file patest_underflow.c
|
||||
@brief Simulate an output buffer underflow condition.
|
||||
Tests whether the stream can be stopped when underflowing buffers.
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.audiomulch.com/portaudio/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (20)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (2048)
|
||||
#define MSEC_PER_BUFFER ( (FRAMES_PER_BUFFER * 1000) / SAMPLE_RATE )
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
typedef struct
|
||||
{
|
||||
float sine[TABLE_SIZE];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
int sleepTime;
|
||||
}
|
||||
paTestData;
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
float *out = (float*)outputBuffer;
|
||||
unsigned long i;
|
||||
int finished = 0;
|
||||
(void) inputBuffer; /* Prevent unused variable warnings. */
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out++ = data->sine[data->left_phase]; /* left */
|
||||
*out++ = data->sine[data->right_phase]; /* right */
|
||||
data->left_phase += 1;
|
||||
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
||||
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
||||
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
||||
}
|
||||
|
||||
/* Cause underflow to occur. */
|
||||
if( data->sleepTime > 0 ) Pa_Sleep( data->sleepTime );
|
||||
data->sleepTime += 1;
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
paTestData data;
|
||||
int i;
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
data.left_phase = data.right_phase = data.sleepTime = 0;
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
patestCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
while( data.sleepTime < (2 * MSEC_PER_BUFFER) )
|
||||
{
|
||||
printf("SleepTime = %d\n", data.sleepTime );
|
||||
Pa_Sleep( data.sleepTime );
|
||||
}
|
||||
|
||||
printf("Try to stop stream.\n");
|
||||
err = Pa_StopStream( stream ); /* */
|
||||
err = Pa_AbortStream( stream ); /* */
|
||||
if( err != paNoError ) goto error;
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
@ -1,284 +0,0 @@
|
||||
/** @file patest_wire.c
|
||||
@brief Pass input directly to output.
|
||||
|
||||
Note that some HW devices, for example many ISA audio cards
|
||||
on PCs, do NOT support full duplex! For a PC, you normally need
|
||||
a PCI based audio card such as the SBLive.
|
||||
|
||||
@author Phil Burk http://www.softsynth.com
|
||||
|
||||
While adapting to V19-API, I excluded configs with framesPerCallback=0
|
||||
because of an assert in file pa_common/pa_process.c. Pieter, Oct 9, 2003.
|
||||
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define SAMPLE_RATE (44100)
|
||||
|
||||
typedef struct WireConfig_s
|
||||
{
|
||||
int isInputInterleaved;
|
||||
int isOutputInterleaved;
|
||||
int numInputChannels;
|
||||
int numOutputChannels;
|
||||
int framesPerCallback;
|
||||
} WireConfig_t;
|
||||
|
||||
#define USE_FLOAT_INPUT (1)
|
||||
#define USE_FLOAT_OUTPUT (1)
|
||||
|
||||
/* Latencies set to defaults. */
|
||||
|
||||
#if USE_FLOAT_INPUT
|
||||
#define INPUT_FORMAT paFloat32
|
||||
typedef float INPUT_SAMPLE;
|
||||
#else
|
||||
#define INPUT_FORMAT paInt16
|
||||
typedef short INPUT_SAMPLE;
|
||||
#endif
|
||||
|
||||
#if USE_FLOAT_OUTPUT
|
||||
#define OUTPUT_FORMAT paFloat32
|
||||
typedef float OUTPUT_SAMPLE;
|
||||
#else
|
||||
#define OUTPUT_FORMAT paInt16
|
||||
typedef short OUTPUT_SAMPLE;
|
||||
#endif
|
||||
|
||||
double gInOutScaler = 1.0;
|
||||
#define CONVERT_IN_TO_OUT(in) ((OUTPUT_SAMPLE) ((in) * gInOutScaler))
|
||||
|
||||
#define INPUT_DEVICE (Pa_GetDefaultInputDevice())
|
||||
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
|
||||
|
||||
static PaError TestConfiguration( WireConfig_t *config );
|
||||
|
||||
static int wireCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData );
|
||||
|
||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||
** It may be called at interrupt level on some machines so don't do anything
|
||||
** that could mess up the system like calling malloc() or free().
|
||||
*/
|
||||
|
||||
static int wireCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
INPUT_SAMPLE *in;
|
||||
OUTPUT_SAMPLE *out;
|
||||
int inStride;
|
||||
int outStride;
|
||||
int inDone = 0;
|
||||
int outDone = 0;
|
||||
WireConfig_t *config = (WireConfig_t *) userData;
|
||||
unsigned int i;
|
||||
int inChannel, outChannel;
|
||||
|
||||
/* This may get called with NULL inputBuffer during initial setup. */
|
||||
if( inputBuffer == NULL) return 0;
|
||||
|
||||
inChannel=0, outChannel=0;
|
||||
while( !(inDone && outDone) )
|
||||
{
|
||||
if( config->isInputInterleaved )
|
||||
{
|
||||
in = ((INPUT_SAMPLE*)inputBuffer) + inChannel;
|
||||
inStride = config->numInputChannels;
|
||||
}
|
||||
else
|
||||
{
|
||||
in = ((INPUT_SAMPLE**)inputBuffer)[inChannel];
|
||||
inStride = 1;
|
||||
}
|
||||
|
||||
if( config->isOutputInterleaved )
|
||||
{
|
||||
out = ((OUTPUT_SAMPLE*)outputBuffer) + outChannel;
|
||||
outStride = config->numOutputChannels;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = ((OUTPUT_SAMPLE**)outputBuffer)[outChannel];
|
||||
outStride = 1;
|
||||
}
|
||||
|
||||
for( i=0; i<framesPerBuffer; i++ )
|
||||
{
|
||||
*out = CONVERT_IN_TO_OUT( *in );
|
||||
out += outStride;
|
||||
in += inStride;
|
||||
}
|
||||
|
||||
if(inChannel < (config->numInputChannels - 1)) inChannel++;
|
||||
else inDone = 1;
|
||||
if(outChannel < (config->numOutputChannels - 1)) outChannel++;
|
||||
else outDone = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaError err;
|
||||
WireConfig_t CONFIG;
|
||||
WireConfig_t *config = &CONFIG;
|
||||
int configIndex = 0;;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Please connect audio signal to input and listen for it on output!\n");
|
||||
printf("input format = %lu\n", INPUT_FORMAT );
|
||||
printf("output format = %lu\n", OUTPUT_FORMAT );
|
||||
printf("input device ID = %d\n", INPUT_DEVICE );
|
||||
printf("output device ID = %d\n", OUTPUT_DEVICE );
|
||||
|
||||
if( INPUT_FORMAT == OUTPUT_FORMAT )
|
||||
{
|
||||
gInOutScaler = 1.0;
|
||||
}
|
||||
else if( (INPUT_FORMAT == paInt16) && (OUTPUT_FORMAT == paFloat32) )
|
||||
{
|
||||
gInOutScaler = 1.0/32768.0;
|
||||
}
|
||||
else if( (INPUT_FORMAT == paFloat32) && (OUTPUT_FORMAT == paInt16) )
|
||||
{
|
||||
gInOutScaler = 32768.0;
|
||||
}
|
||||
|
||||
for( config->isInputInterleaved = 0; config->isInputInterleaved < 2; config->isInputInterleaved++ )
|
||||
{
|
||||
for( config->isOutputInterleaved = 0; config->isOutputInterleaved < 2; config->isOutputInterleaved++ )
|
||||
{
|
||||
for( config->numInputChannels = 1; config->numInputChannels < 3; config->numInputChannels++ )
|
||||
{
|
||||
for( config->numOutputChannels = 1; config->numOutputChannels < 3; config->numOutputChannels++ )
|
||||
{
|
||||
/* If framesPerCallback = 0, assertion fails in file pa_common/pa_process.c, line 1413: EX. */
|
||||
for( config->framesPerCallback = 64; config->framesPerCallback < 129; config->framesPerCallback += 64 )
|
||||
{
|
||||
printf("-----------------------------------------------\n" );
|
||||
printf("Configuration #%d\n", configIndex++ );
|
||||
err = TestConfiguration( config );
|
||||
/* Give user a chance to bail out. */
|
||||
if( err == 1 )
|
||||
{
|
||||
err = paNoError;
|
||||
goto done;
|
||||
}
|
||||
else if( err != paNoError ) goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
printf("Full duplex sound test complete.\n"); fflush(stdout);
|
||||
printf("Hit ENTER to quit.\n"); fflush(stdout);
|
||||
getchar();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
printf("Hit ENTER to quit.\n"); fflush(stdout);
|
||||
getchar();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PaError TestConfiguration( WireConfig_t *config )
|
||||
{
|
||||
int c;
|
||||
PaError err;
|
||||
PaStream *stream;
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
|
||||
printf("input %sinterleaved!\n", (config->isInputInterleaved ? " " : "NOT ") );
|
||||
printf("output %sinterleaved!\n", (config->isOutputInterleaved ? " " : "NOT ") );
|
||||
printf("input channels = %d\n", config->numInputChannels );
|
||||
printf("output channels = %d\n", config->numOutputChannels );
|
||||
printf("framesPerCallback = %d\n", config->framesPerCallback );
|
||||
|
||||
inputParameters.device = INPUT_DEVICE; /* default input device */
|
||||
inputParameters.channelCount = config->numInputChannels;
|
||||
inputParameters.sampleFormat = INPUT_FORMAT | (config->isInputInterleaved ? 0 : paNonInterleaved);
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
outputParameters.device = OUTPUT_DEVICE; /* default output device */
|
||||
outputParameters.channelCount = config->numOutputChannels;
|
||||
outputParameters.sampleFormat = OUTPUT_FORMAT | (config->isOutputInterleaved ? 0 : paNonInterleaved);
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
config->framesPerCallback, /* frames per buffer */
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
wireCallback,
|
||||
config );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Hit ENTER for next configuration, or 'q' to quit.\n"); fflush(stdout);
|
||||
c = getchar();
|
||||
|
||||
printf("Closing stream.\n");
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
if( c == 'q' ) return 1;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
@ -1,147 +0,0 @@
|
||||
/** @file patest_write_sine.c
|
||||
@brief Play a sine wave for several seconds using the blocking API (Pa_WriteStream())
|
||||
@author Ross Bencina <rossb@audiomulch.com>
|
||||
@author Phil Burk <philburk@softsynth.com>
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com/
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "portaudio.h"
|
||||
|
||||
#define NUM_SECONDS (5)
|
||||
#define SAMPLE_RATE (44100)
|
||||
#define FRAMES_PER_BUFFER (1024)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265)
|
||||
#endif
|
||||
|
||||
#define TABLE_SIZE (200)
|
||||
|
||||
|
||||
int main(void);
|
||||
int main(void)
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
float buffer[FRAMES_PER_BUFFER][2]; /* stereo output buffer */
|
||||
float sine[TABLE_SIZE]; /* sine wavetable */
|
||||
int left_phase = 0;
|
||||
int right_phase = 0;
|
||||
int left_inc = 1;
|
||||
int right_inc = 3; /* higher pitch so we can distinguish left and right. */
|
||||
int i, j, k;
|
||||
int bufferCount;
|
||||
|
||||
|
||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
for( i=0; i<TABLE_SIZE; i++ )
|
||||
{
|
||||
sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
||||
}
|
||||
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
outputParameters.channelCount = 2; /* stereo output */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL, /* no input */
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
NULL, /* no callback, use blocking API */
|
||||
NULL ); /* no callback, so no callback userData */
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
|
||||
printf( "Play 3 times, higher each time.\n" );
|
||||
|
||||
for( k=0; k < 3; ++k )
|
||||
{
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
printf("Play for %d seconds.\n", NUM_SECONDS );
|
||||
|
||||
bufferCount = ((NUM_SECONDS * SAMPLE_RATE) / FRAMES_PER_BUFFER);
|
||||
|
||||
for( i=0; i < bufferCount; i++ )
|
||||
{
|
||||
for( j=0; j < FRAMES_PER_BUFFER; j++ )
|
||||
{
|
||||
buffer[j][0] = sine[left_phase]; /* left */
|
||||
buffer[j][1] = sine[right_phase]; /* right */
|
||||
left_phase += left_inc;
|
||||
if( left_phase >= TABLE_SIZE ) left_phase -= TABLE_SIZE;
|
||||
right_phase += right_inc;
|
||||
if( right_phase >= TABLE_SIZE ) right_phase -= TABLE_SIZE;
|
||||
}
|
||||
|
||||
err = Pa_WriteStream( stream, buffer, FRAMES_PER_BUFFER );
|
||||
if( err != paNoError ) goto error;
|
||||
}
|
||||
|
||||
err = Pa_StopStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
++left_inc;
|
||||
++right_inc;
|
||||
|
||||
Pa_Sleep( 1000 );
|
||||
}
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto error;
|
||||
|
||||
Pa_Terminate();
|
||||
printf("Test finished.\n");
|
||||
|
||||
return err;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
return err;
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* recplay.c
|
||||
* Phil Burk
|
||||
* Minimal record and playback test.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef __STDC__
|
||||
/* #include <getopt.h> */
|
||||
#endif /* __STDC__ */
|
||||
#include <fcntl.h>
|
||||
#ifdef __STDC__
|
||||
#include <string.h>
|
||||
#else /* __STDC__ */
|
||||
#include <strings.h>
|
||||
#endif /* __STDC__ */
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
#define NUM_BYTES (64*1024)
|
||||
#define BLOCK_SIZE (4*1024)
|
||||
|
||||
#define AUDIO "/dev/dsp"
|
||||
|
||||
char buffer[NUM_BYTES];
|
||||
|
||||
int audioDev = 0;
|
||||
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int numLeft;
|
||||
char *ptr;
|
||||
int num;
|
||||
int samplesize;
|
||||
|
||||
/********** RECORD ********************/
|
||||
/* Open audio device. */
|
||||
audioDev = open (AUDIO, O_RDONLY, 0);
|
||||
if (audioDev == -1)
|
||||
{
|
||||
perror (AUDIO);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* Set to 16 bit samples. */
|
||||
samplesize = 16;
|
||||
ioctl(audioDev, SNDCTL_DSP_SAMPLESIZE, &samplesize);
|
||||
if (samplesize != 16)
|
||||
{
|
||||
perror("Unable to set the sample size.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Record in blocks */
|
||||
printf("Begin recording.\n");
|
||||
numLeft = NUM_BYTES;
|
||||
ptr = buffer;
|
||||
while( numLeft >= BLOCK_SIZE )
|
||||
{
|
||||
if ( (num = read (audioDev, ptr, BLOCK_SIZE)) < 0 )
|
||||
{
|
||||
perror (AUDIO);
|
||||
exit (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Read %d bytes\n", num);
|
||||
ptr += num;
|
||||
numLeft -= num;
|
||||
}
|
||||
}
|
||||
|
||||
close( audioDev );
|
||||
|
||||
/********** PLAYBACK ********************/
|
||||
/* Open audio device for writing. */
|
||||
audioDev = open (AUDIO, O_WRONLY, 0);
|
||||
if (audioDev == -1)
|
||||
{
|
||||
perror (AUDIO);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* Set to 16 bit samples. */
|
||||
samplesize = 16;
|
||||
ioctl(audioDev, SNDCTL_DSP_SAMPLESIZE, &samplesize);
|
||||
if (samplesize != 16)
|
||||
{
|
||||
perror("Unable to set the sample size.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Play in blocks */
|
||||
printf("Begin playing.\n");
|
||||
numLeft = NUM_BYTES;
|
||||
ptr = buffer;
|
||||
while( numLeft >= BLOCK_SIZE )
|
||||
{
|
||||
if ( (num = write (audioDev, ptr, BLOCK_SIZE)) < 0 )
|
||||
{
|
||||
perror (AUDIO);
|
||||
exit (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Wrote %d bytes\n", num);
|
||||
ptr += num;
|
||||
numLeft -= num;
|
||||
}
|
||||
}
|
||||
|
||||
close( audioDev );
|
||||
}
|
||||
@ -1,616 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Simplified DirectSound interface.
|
||||
*
|
||||
* Author: Phil Burk & Robert Marsanyi
|
||||
*
|
||||
* PortAudio Portable Real-Time Audio Library
|
||||
* For more information see: http://www.softsynth.com/portaudio/
|
||||
* DirectSound Implementation
|
||||
* Copyright (c) 1999-2000 Phil Burk & Robert Marsanyi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dsound_wrapper.h"
|
||||
#include "pa_trace.h"
|
||||
|
||||
/*
|
||||
Rather than linking with dxguid.a or using "#define INITGUID" to force a
|
||||
header file to instantiate the required GUID(s), we define them directly
|
||||
below.
|
||||
*/
|
||||
#include <initguid.h> // needed for the DEFINE_GUID macro
|
||||
DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
|
||||
|
||||
|
||||
/************************************************************************************/
|
||||
DSoundEntryPoints dswDSoundEntryPoints = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
/************************************************************************************/
|
||||
static HRESULT WINAPI DummyDirectSoundCreate(LPGUID lpcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter)
|
||||
{
|
||||
(void)lpcGuidDevice; /* unused parameter */
|
||||
(void)ppDS; /* unused parameter */
|
||||
(void)pUnkOuter; /* unused parameter */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DummyDirectSoundEnumerateW(LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext)
|
||||
{
|
||||
(void)lpDSEnumCallback; /* unused parameter */
|
||||
(void)lpContext; /* unused parameter */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DummyDirectSoundEnumerateA(LPDSENUMCALLBACKA lpDSEnumCallback, LPVOID lpContext)
|
||||
{
|
||||
(void)lpDSEnumCallback; /* unused parameter */
|
||||
(void)lpContext; /* unused parameter */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DummyDirectSoundCaptureCreate(LPGUID lpcGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter)
|
||||
{
|
||||
(void)lpcGUID; /* unused parameter */
|
||||
(void)lplpDSC; /* unused parameter */
|
||||
(void)pUnkOuter; /* unused parameter */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DummyDirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW lpDSCEnumCallback, LPVOID lpContext)
|
||||
{
|
||||
(void)lpDSCEnumCallback; /* unused parameter */
|
||||
(void)lpContext; /* unused parameter */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DummyDirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA lpDSCEnumCallback, LPVOID lpContext)
|
||||
{
|
||||
(void)lpDSCEnumCallback; /* unused parameter */
|
||||
(void)lpContext; /* unused parameter */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
/************************************************************************************/
|
||||
void DSW_InitializeDSoundEntryPoints(void)
|
||||
{
|
||||
dswDSoundEntryPoints.hInstance_ = LoadLibrary("dsound.dll");
|
||||
if( dswDSoundEntryPoints.hInstance_ != NULL )
|
||||
{
|
||||
dswDSoundEntryPoints.DirectSoundCreate =
|
||||
(HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN))
|
||||
GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCreate" );
|
||||
if( dswDSoundEntryPoints.DirectSoundCreate == NULL )
|
||||
dswDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
|
||||
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateW =
|
||||
(HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
|
||||
GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundEnumerateW" );
|
||||
if( dswDSoundEntryPoints.DirectSoundEnumerateW == NULL )
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
|
||||
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateA =
|
||||
(HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
|
||||
GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundEnumerateA" );
|
||||
if( dswDSoundEntryPoints.DirectSoundEnumerateA == NULL )
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
|
||||
|
||||
dswDSoundEntryPoints.DirectSoundCaptureCreate =
|
||||
(HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN))
|
||||
GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCaptureCreate" );
|
||||
if( dswDSoundEntryPoints.DirectSoundCaptureCreate == NULL )
|
||||
dswDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
|
||||
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateW =
|
||||
(HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
|
||||
GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateW" );
|
||||
if( dswDSoundEntryPoints.DirectSoundCaptureEnumerateW == NULL )
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
|
||||
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateA =
|
||||
(HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
|
||||
GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateA" );
|
||||
if( dswDSoundEntryPoints.DirectSoundCaptureEnumerateA == NULL )
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialize with dummy entry points to make live easy when ds isn't present */
|
||||
dswDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
|
||||
dswDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
|
||||
}
|
||||
}
|
||||
/************************************************************************************/
|
||||
void DSW_TerminateDSoundEntryPoints(void)
|
||||
{
|
||||
if( dswDSoundEntryPoints.hInstance_ != NULL )
|
||||
{
|
||||
FreeLibrary( dswDSoundEntryPoints.hInstance_ );
|
||||
dswDSoundEntryPoints.hInstance_ = NULL;
|
||||
/* ensure that we crash reliably if the entry points arent initialised */
|
||||
dswDSoundEntryPoints.DirectSoundCreate = 0;
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateW = 0;
|
||||
dswDSoundEntryPoints.DirectSoundEnumerateA = 0;
|
||||
dswDSoundEntryPoints.DirectSoundCaptureCreate = 0;
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateW = 0;
|
||||
dswDSoundEntryPoints.DirectSoundCaptureEnumerateA = 0;
|
||||
}
|
||||
}
|
||||
/************************************************************************************/
|
||||
void DSW_Term( DSoundWrapper *dsw )
|
||||
{
|
||||
// Cleanup the sound buffers
|
||||
if (dsw->dsw_OutputBuffer)
|
||||
{
|
||||
IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer );
|
||||
IDirectSoundBuffer_Release( dsw->dsw_OutputBuffer );
|
||||
dsw->dsw_OutputBuffer = NULL;
|
||||
}
|
||||
|
||||
if (dsw->dsw_InputBuffer)
|
||||
{
|
||||
IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer );
|
||||
IDirectSoundCaptureBuffer_Release( dsw->dsw_InputBuffer );
|
||||
dsw->dsw_InputBuffer = NULL;
|
||||
}
|
||||
|
||||
if (dsw->dsw_pDirectSoundCapture)
|
||||
{
|
||||
IDirectSoundCapture_Release( dsw->dsw_pDirectSoundCapture );
|
||||
dsw->dsw_pDirectSoundCapture = NULL;
|
||||
}
|
||||
|
||||
if (dsw->dsw_pDirectSound)
|
||||
{
|
||||
IDirectSound_Release( dsw->dsw_pDirectSound );
|
||||
dsw->dsw_pDirectSound = NULL;
|
||||
}
|
||||
}
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_Init( DSoundWrapper *dsw )
|
||||
{
|
||||
memset( dsw, 0, sizeof(DSoundWrapper) );
|
||||
return 0;
|
||||
}
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_InitOutputDevice( DSoundWrapper *dsw, LPGUID lpGUID )
|
||||
{
|
||||
// Create the DS object
|
||||
HRESULT hr = dswDSoundEntryPoints.DirectSoundCreate( lpGUID, &dsw->dsw_pDirectSound, NULL );
|
||||
if( hr != DS_OK ) return hr;
|
||||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer )
|
||||
{
|
||||
DWORD dwDataLen;
|
||||
DWORD playCursor;
|
||||
HRESULT result;
|
||||
LPDIRECTSOUNDBUFFER pPrimaryBuffer;
|
||||
HWND hWnd;
|
||||
HRESULT hr;
|
||||
WAVEFORMATEX wfFormat;
|
||||
DSBUFFERDESC primaryDesc;
|
||||
DSBUFFERDESC secondaryDesc;
|
||||
unsigned char* pDSBuffData;
|
||||
LARGE_INTEGER counterFrequency;
|
||||
|
||||
dsw->dsw_OutputSize = bytesPerBuffer;
|
||||
dsw->dsw_OutputRunning = FALSE;
|
||||
dsw->dsw_OutputUnderflows = 0;
|
||||
dsw->dsw_FramesWritten = 0;
|
||||
dsw->dsw_BytesPerOutputFrame = nChannels * sizeof(short);
|
||||
|
||||
// We were using getForegroundWindow() but sometimes the ForegroundWindow may not be the
|
||||
// applications's window. Also if that window is closed before the Buffer is closed
|
||||
// then DirectSound can crash. (Thanks for Scott Patterson for reporting this.)
|
||||
// So we will use GetDesktopWindow() which was suggested by Miller Puckette.
|
||||
// hWnd = GetForegroundWindow();
|
||||
//
|
||||
// FIXME: The example code I have on the net creates a hidden window that
|
||||
// is managed by our code - I think we should do that - one hidden
|
||||
// window for the whole of Pa_DS
|
||||
//
|
||||
hWnd = GetDesktopWindow();
|
||||
|
||||
// Set cooperative level to DSSCL_EXCLUSIVE so that we can get 16 bit output, 44.1 KHz.
|
||||
// Exclusize also prevents unexpected sounds from other apps during a performance.
|
||||
if ((hr = IDirectSound_SetCooperativeLevel( dsw->dsw_pDirectSound,
|
||||
hWnd, DSSCL_EXCLUSIVE)) != DS_OK)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Create primary buffer and set format just so we can specify our custom format.
|
||||
// Otherwise we would be stuck with the default which might be 8 bit or 22050 Hz.
|
||||
// Setup the primary buffer description
|
||||
ZeroMemory(&primaryDesc, sizeof(DSBUFFERDESC));
|
||||
primaryDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
primaryDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; // all panning, mixing, etc done by synth
|
||||
primaryDesc.dwBufferBytes = 0;
|
||||
primaryDesc.lpwfxFormat = NULL;
|
||||
// Create the buffer
|
||||
if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound,
|
||||
&primaryDesc, &pPrimaryBuffer, NULL)) != DS_OK) return result;
|
||||
// Define the buffer format
|
||||
wfFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfFormat.nChannels = nChannels;
|
||||
wfFormat.nSamplesPerSec = nFrameRate;
|
||||
wfFormat.wBitsPerSample = 8 * sizeof(short);
|
||||
wfFormat.nBlockAlign = (WORD)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8));
|
||||
wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
|
||||
wfFormat.cbSize = 0; /* No extended format info. */
|
||||
// Set the primary buffer's format
|
||||
if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, &wfFormat)) != DS_OK) return result;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Setup the secondary buffer description
|
||||
ZeroMemory(&secondaryDesc, sizeof(DSBUFFERDESC));
|
||||
secondaryDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
secondaryDesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
|
||||
secondaryDesc.dwBufferBytes = bytesPerBuffer;
|
||||
secondaryDesc.lpwfxFormat = &wfFormat;
|
||||
// Create the secondary buffer
|
||||
if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound,
|
||||
&secondaryDesc, &dsw->dsw_OutputBuffer, NULL)) != DS_OK) return result;
|
||||
// Lock the DS buffer
|
||||
if ((result = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, 0, dsw->dsw_OutputSize, (LPVOID*)&pDSBuffData,
|
||||
&dwDataLen, NULL, 0, 0)) != DS_OK) return result;
|
||||
// Zero the DS buffer
|
||||
ZeroMemory(pDSBuffData, dwDataLen);
|
||||
// Unlock the DS buffer
|
||||
if ((result = IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) return result;
|
||||
if( QueryPerformanceFrequency( &counterFrequency ) )
|
||||
{
|
||||
int framesInBuffer = bytesPerBuffer / (nChannels * sizeof(short));
|
||||
dsw->dsw_CounterTicksPerBuffer.QuadPart = (counterFrequency.QuadPart * framesInBuffer) / nFrameRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsw->dsw_CounterTicksPerBuffer.QuadPart = 0;
|
||||
}
|
||||
// Let DSound set the starting write position because if we set it to zero, it looks like the
|
||||
// buffer is full to begin with. This causes a long pause before sound starts when using large buffers.
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &dsw->dsw_WriteOffset );
|
||||
if( hr != DS_OK )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
dsw->dsw_FramesWritten = dsw->dsw_WriteOffset / dsw->dsw_BytesPerOutputFrame;
|
||||
/* printf("DSW_InitOutputBuffer: playCursor = %d, writeCursor = %d\n", playCursor, dsw->dsw_WriteOffset ); */
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_StartOutput( DSoundWrapper *dsw )
|
||||
{
|
||||
HRESULT hr;
|
||||
QueryPerformanceCounter( &dsw->dsw_LastPlayTime );
|
||||
dsw->dsw_LastPlayCursor = 0;
|
||||
dsw->dsw_FramesPlayed = 0;
|
||||
hr = IDirectSoundBuffer_SetCurrentPosition( dsw->dsw_OutputBuffer, 0 );
|
||||
if( hr != DS_OK )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
// Start the buffer playback in a loop.
|
||||
if( dsw->dsw_OutputBuffer != NULL )
|
||||
{
|
||||
hr = IDirectSoundBuffer_Play( dsw->dsw_OutputBuffer, 0, 0, DSBPLAY_LOOPING );
|
||||
if( hr != DS_OK )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
dsw->dsw_OutputRunning = TRUE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_StopOutput( DSoundWrapper *dsw )
|
||||
{
|
||||
// Stop the buffer playback
|
||||
if( dsw->dsw_OutputBuffer != NULL )
|
||||
{
|
||||
dsw->dsw_OutputRunning = FALSE;
|
||||
return IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer );
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_QueryOutputFilled( DSoundWrapper *dsw, long *bytesFilledPtr )
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD playCursor;
|
||||
DWORD writeCursor;
|
||||
long bytesFilled;
|
||||
// Query to see where play position is.
|
||||
// We don't need the writeCursor but sometimes DirectSound doesn't handle NULLS correctly
|
||||
// so let's pass a pointer just to be safe.
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &writeCursor );
|
||||
if( hr != DS_OK )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
bytesFilled = dsw->dsw_WriteOffset - playCursor;
|
||||
if( bytesFilled < 0 ) bytesFilled += dsw->dsw_OutputSize; // unwrap offset
|
||||
*bytesFilledPtr = bytesFilled;
|
||||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Determine how much space can be safely written to in DS buffer.
|
||||
* Detect underflows and overflows.
|
||||
* Does not allow writing into safety gap maintained by DirectSound.
|
||||
*/
|
||||
HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty )
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD playCursor;
|
||||
DWORD writeCursor;
|
||||
long numBytesEmpty;
|
||||
long playWriteGap;
|
||||
// Query to see how much room is in buffer.
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &writeCursor );
|
||||
if( hr != DS_OK )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
// Determine size of gap between playIndex and WriteIndex that we cannot write into.
|
||||
playWriteGap = writeCursor - playCursor;
|
||||
if( playWriteGap < 0 ) playWriteGap += dsw->dsw_OutputSize; // unwrap
|
||||
/* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */
|
||||
/* Attempt to detect playCursor wrap-around and correct it. */
|
||||
if( dsw->dsw_OutputRunning && (dsw->dsw_CounterTicksPerBuffer.QuadPart != 0) )
|
||||
{
|
||||
/* How much time has elapsed since last check. */
|
||||
LARGE_INTEGER currentTime;
|
||||
LARGE_INTEGER elapsedTime;
|
||||
long bytesPlayed;
|
||||
long bytesExpected;
|
||||
long buffersWrapped;
|
||||
QueryPerformanceCounter( ¤tTime );
|
||||
elapsedTime.QuadPart = currentTime.QuadPart - dsw->dsw_LastPlayTime.QuadPart;
|
||||
dsw->dsw_LastPlayTime = currentTime;
|
||||
/* How many bytes does DirectSound say have been played. */
|
||||
bytesPlayed = playCursor - dsw->dsw_LastPlayCursor;
|
||||
if( bytesPlayed < 0 ) bytesPlayed += dsw->dsw_OutputSize; // unwrap
|
||||
dsw->dsw_LastPlayCursor = playCursor;
|
||||
/* Calculate how many bytes we would have expected to been played by now. */
|
||||
bytesExpected = (long) ((elapsedTime.QuadPart * dsw->dsw_OutputSize) / dsw->dsw_CounterTicksPerBuffer.QuadPart);
|
||||
buffersWrapped = (bytesExpected - bytesPlayed) / dsw->dsw_OutputSize;
|
||||
if( buffersWrapped > 0 )
|
||||
{
|
||||
playCursor += (buffersWrapped * dsw->dsw_OutputSize);
|
||||
bytesPlayed += (buffersWrapped * dsw->dsw_OutputSize);
|
||||
}
|
||||
/* Maintain frame output cursor. */
|
||||
dsw->dsw_FramesPlayed += (bytesPlayed / dsw->dsw_BytesPerOutputFrame);
|
||||
}
|
||||
numBytesEmpty = playCursor - dsw->dsw_WriteOffset;
|
||||
if( numBytesEmpty < 0 ) numBytesEmpty += dsw->dsw_OutputSize; // unwrap offset
|
||||
/* Have we underflowed? */
|
||||
if( numBytesEmpty > (dsw->dsw_OutputSize - playWriteGap) )
|
||||
{
|
||||
if( dsw->dsw_OutputRunning )
|
||||
{
|
||||
dsw->dsw_OutputUnderflows += 1;
|
||||
}
|
||||
dsw->dsw_WriteOffset = writeCursor;
|
||||
numBytesEmpty = dsw->dsw_OutputSize - playWriteGap;
|
||||
}
|
||||
*bytesEmpty = numBytesEmpty;
|
||||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_ZeroEmptySpace( DSoundWrapper *dsw )
|
||||
{
|
||||
HRESULT hr;
|
||||
LPBYTE lpbuf1 = NULL;
|
||||
LPBYTE lpbuf2 = NULL;
|
||||
DWORD dwsize1 = 0;
|
||||
DWORD dwsize2 = 0;
|
||||
long bytesEmpty;
|
||||
hr = DSW_QueryOutputSpace( dsw, &bytesEmpty ); // updates dsw_FramesPlayed
|
||||
if (hr != DS_OK) return hr;
|
||||
if( bytesEmpty == 0 ) return DS_OK;
|
||||
// Lock free space in the DS
|
||||
hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, bytesEmpty, (void **) &lpbuf1, &dwsize1,
|
||||
(void **) &lpbuf2, &dwsize2, 0);
|
||||
if (hr == DS_OK)
|
||||
{
|
||||
// Copy the buffer into the DS
|
||||
ZeroMemory(lpbuf1, dwsize1);
|
||||
if(lpbuf2 != NULL)
|
||||
{
|
||||
ZeroMemory(lpbuf2, dwsize2);
|
||||
}
|
||||
// Update our buffer offset and unlock sound buffer
|
||||
dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize;
|
||||
IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
|
||||
dsw->dsw_FramesWritten += bytesEmpty / dsw->dsw_BytesPerOutputFrame;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_WriteBlock( DSoundWrapper *dsw, char *buf, long numBytes )
|
||||
{
|
||||
HRESULT hr;
|
||||
LPBYTE lpbuf1 = NULL;
|
||||
LPBYTE lpbuf2 = NULL;
|
||||
DWORD dwsize1 = 0;
|
||||
DWORD dwsize2 = 0;
|
||||
// Lock free space in the DS
|
||||
hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, numBytes, (void **) &lpbuf1, &dwsize1,
|
||||
(void **) &lpbuf2, &dwsize2, 0);
|
||||
if (hr == DS_OK)
|
||||
{
|
||||
// Copy the buffer into the DS
|
||||
CopyMemory(lpbuf1, buf, dwsize1);
|
||||
if(lpbuf2 != NULL)
|
||||
{
|
||||
CopyMemory(lpbuf2, buf+dwsize1, dwsize2);
|
||||
}
|
||||
// Update our buffer offset and unlock sound buffer
|
||||
dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize;
|
||||
IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
|
||||
dsw->dsw_FramesWritten += numBytes / dsw->dsw_BytesPerOutputFrame;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
DWORD DSW_GetOutputStatus( DSoundWrapper *dsw )
|
||||
{
|
||||
DWORD status;
|
||||
if (IDirectSoundBuffer_GetStatus( dsw->dsw_OutputBuffer, &status ) != DS_OK)
|
||||
return( DSERR_INVALIDPARAM );
|
||||
else
|
||||
return( status );
|
||||
}
|
||||
|
||||
/* These routines are used to support audio input.
|
||||
* Do NOT compile these calls when using NT4 because it does
|
||||
* not support the entry points.
|
||||
*/
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_InitInputDevice( DSoundWrapper *dsw, LPGUID lpGUID )
|
||||
{
|
||||
HRESULT hr = dswDSoundEntryPoints.DirectSoundCaptureCreate( lpGUID, &dsw->dsw_pDirectSoundCapture, NULL );
|
||||
if( hr != DS_OK ) return hr;
|
||||
return hr;
|
||||
}
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_InitInputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer )
|
||||
{
|
||||
DSCBUFFERDESC captureDesc;
|
||||
WAVEFORMATEX wfFormat;
|
||||
HRESULT result;
|
||||
|
||||
dsw->dsw_BytesPerInputFrame = nChannels * sizeof(short);
|
||||
|
||||
// Define the buffer format
|
||||
wfFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfFormat.nChannels = nChannels;
|
||||
wfFormat.nSamplesPerSec = nFrameRate;
|
||||
wfFormat.wBitsPerSample = 8 * sizeof(short);
|
||||
wfFormat.nBlockAlign = (WORD)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8));
|
||||
wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
|
||||
wfFormat.cbSize = 0; /* No extended format info. */
|
||||
dsw->dsw_InputSize = bytesPerBuffer;
|
||||
// ----------------------------------------------------------------------
|
||||
// Setup the secondary buffer description
|
||||
ZeroMemory(&captureDesc, sizeof(DSCBUFFERDESC));
|
||||
captureDesc.dwSize = sizeof(DSCBUFFERDESC);
|
||||
captureDesc.dwFlags = 0;
|
||||
captureDesc.dwBufferBytes = bytesPerBuffer;
|
||||
captureDesc.lpwfxFormat = &wfFormat;
|
||||
// Create the capture buffer
|
||||
if ((result = IDirectSoundCapture_CreateCaptureBuffer( dsw->dsw_pDirectSoundCapture,
|
||||
&captureDesc, &dsw->dsw_InputBuffer, NULL)) != DS_OK) return result;
|
||||
dsw->dsw_ReadOffset = 0; // reset last read position to start of buffer
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_StartInput( DSoundWrapper *dsw )
|
||||
{
|
||||
// Start the buffer playback
|
||||
if( dsw->dsw_InputBuffer != NULL )
|
||||
{
|
||||
return IDirectSoundCaptureBuffer_Start( dsw->dsw_InputBuffer, DSCBSTART_LOOPING );
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_StopInput( DSoundWrapper *dsw )
|
||||
{
|
||||
// Stop the buffer playback
|
||||
if( dsw->dsw_InputBuffer != NULL )
|
||||
{
|
||||
return IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer );
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_QueryInputFilled( DSoundWrapper *dsw, long *bytesFilled )
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD capturePos;
|
||||
DWORD readPos;
|
||||
long filled;
|
||||
// Query to see how much data is in buffer.
|
||||
// We don't need the capture position but sometimes DirectSound doesn't handle NULLS correctly
|
||||
// so let's pass a pointer just to be safe.
|
||||
hr = IDirectSoundCaptureBuffer_GetCurrentPosition( dsw->dsw_InputBuffer, &capturePos, &readPos );
|
||||
if( hr != DS_OK )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
filled = readPos - dsw->dsw_ReadOffset;
|
||||
if( filled < 0 ) filled += dsw->dsw_InputSize; // unwrap offset
|
||||
*bytesFilled = filled;
|
||||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
HRESULT DSW_ReadBlock( DSoundWrapper *dsw, char *buf, long numBytes )
|
||||
{
|
||||
HRESULT hr;
|
||||
LPBYTE lpbuf1 = NULL;
|
||||
LPBYTE lpbuf2 = NULL;
|
||||
DWORD dwsize1 = 0;
|
||||
DWORD dwsize2 = 0;
|
||||
// Lock free space in the DS
|
||||
hr = IDirectSoundCaptureBuffer_Lock ( dsw->dsw_InputBuffer, dsw->dsw_ReadOffset, numBytes, (void **) &lpbuf1, &dwsize1,
|
||||
(void **) &lpbuf2, &dwsize2, 0);
|
||||
if (hr == DS_OK)
|
||||
{
|
||||
// Copy from DS to the buffer
|
||||
CopyMemory( buf, lpbuf1, dwsize1);
|
||||
if(lpbuf2 != NULL)
|
||||
{
|
||||
CopyMemory( buf+dwsize1, lpbuf2, dwsize2);
|
||||
}
|
||||
// Update our buffer offset and unlock sound buffer
|
||||
dsw->dsw_ReadOffset = (dsw->dsw_ReadOffset + dwsize1 + dwsize2) % dsw->dsw_InputSize;
|
||||
IDirectSoundCaptureBuffer_Unlock ( dsw->dsw_InputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
@ -1,130 +0,0 @@
|
||||
#ifndef __DSOUND_WRAPPER_H
|
||||
#define __DSOUND_WRAPPER_H
|
||||
/*
|
||||
* $Id$
|
||||
* Simplified DirectSound interface.
|
||||
*
|
||||
* Author: Phil Burk & Robert Marsanyi
|
||||
*
|
||||
* For PortAudio Portable Real-Time Audio Library
|
||||
* For more information see: http://www.softsynth.com/portaudio/
|
||||
* DirectSound Implementation
|
||||
* Copyright (c) 1999-2000 Phil Burk & Robert Marsanyi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/* on Borland compilers, WIN32 doesn't seem to be defined by default, which
|
||||
breaks DSound.h. Adding the define here fixes the problem. - rossb. */
|
||||
#ifdef __BORLANDC__
|
||||
#if !defined(WIN32)
|
||||
#define WIN32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
We are only using DX3 in here, no need to polute the namespace - davidv
|
||||
*/
|
||||
#define DIRECTSOUND_VERSION 0x0300
|
||||
|
||||
#include <DSound.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HINSTANCE hInstance_;
|
||||
|
||||
HRESULT (WINAPI *DirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
|
||||
HRESULT (WINAPI *DirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
|
||||
HRESULT (WINAPI *DirectSoundEnumerateA)(LPDSENUMCALLBACKA, LPVOID);
|
||||
|
||||
HRESULT (WINAPI *DirectSoundCaptureCreate)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN);
|
||||
HRESULT (WINAPI *DirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
|
||||
HRESULT (WINAPI *DirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA, LPVOID);
|
||||
}DSoundEntryPoints;
|
||||
|
||||
extern DSoundEntryPoints dswDSoundEntryPoints;
|
||||
|
||||
void DSW_InitializeDSoundEntryPoints(void);
|
||||
void DSW_TerminateDSoundEntryPoints(void);
|
||||
|
||||
#define DSW_NUM_POSITIONS (4)
|
||||
#define DSW_NUM_EVENTS (5)
|
||||
#define DSW_TERMINATION_EVENT (DSW_NUM_POSITIONS)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Output */
|
||||
LPDIRECTSOUND dsw_pDirectSound;
|
||||
LPDIRECTSOUNDBUFFER dsw_OutputBuffer;
|
||||
DWORD dsw_WriteOffset; /* last write position */
|
||||
INT dsw_OutputSize;
|
||||
INT dsw_BytesPerOutputFrame;
|
||||
/* Try to detect play buffer underflows. */
|
||||
LARGE_INTEGER dsw_CounterTicksPerBuffer; /* counter ticks it should take to play a full buffer */
|
||||
LARGE_INTEGER dsw_LastPlayTime;
|
||||
UINT dsw_LastPlayCursor;
|
||||
UINT dsw_OutputUnderflows;
|
||||
BOOL dsw_OutputRunning;
|
||||
/* use double which lets us can play for several thousand years with enough precision */
|
||||
double dsw_FramesWritten;
|
||||
double dsw_FramesPlayed;
|
||||
/* Input */
|
||||
INT dsw_BytesPerInputFrame;
|
||||
LPDIRECTSOUNDCAPTURE dsw_pDirectSoundCapture;
|
||||
LPDIRECTSOUNDCAPTUREBUFFER dsw_InputBuffer;
|
||||
UINT dsw_ReadOffset; /* last read position */
|
||||
UINT dsw_InputSize;
|
||||
} DSoundWrapper;
|
||||
|
||||
HRESULT DSW_Init( DSoundWrapper *dsw );
|
||||
void DSW_Term( DSoundWrapper *dsw );
|
||||
HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate,
|
||||
WORD nChannels, int bufSize );
|
||||
HRESULT DSW_StartOutput( DSoundWrapper *dsw );
|
||||
HRESULT DSW_StopOutput( DSoundWrapper *dsw );
|
||||
DWORD DSW_GetOutputStatus( DSoundWrapper *dsw );
|
||||
HRESULT DSW_WriteBlock( DSoundWrapper *dsw, char *buf, long numBytes );
|
||||
HRESULT DSW_ZeroEmptySpace( DSoundWrapper *dsw );
|
||||
HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty );
|
||||
HRESULT DSW_Enumerate( DSoundWrapper *dsw );
|
||||
|
||||
HRESULT DSW_InitInputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate,
|
||||
WORD nChannels, int bufSize );
|
||||
HRESULT DSW_StartInput( DSoundWrapper *dsw );
|
||||
HRESULT DSW_StopInput( DSoundWrapper *dsw );
|
||||
HRESULT DSW_ReadBlock( DSoundWrapper *dsw, char *buf, long numBytes );
|
||||
HRESULT DSW_QueryInputFilled( DSoundWrapper *dsw, long *bytesFilled );
|
||||
HRESULT DSW_QueryOutputFilled( DSoundWrapper *dsw, long *bytesFilled );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __DSOUND_WRAPPER_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,82 +0,0 @@
|
||||
Notes about WDM-KS host API
|
||||
---------------------------
|
||||
|
||||
Status history
|
||||
--------------
|
||||
10th November 2005:
|
||||
Made following changes:
|
||||
* OpenStream: Try all PaSampleFormats internally if the the chosen
|
||||
format is not supported natively. This fixed several problems
|
||||
with soundcards that soundcards that did not take kindly to
|
||||
using 24-bit 3-byte formats.
|
||||
* OpenStream: Make the minimum framesPerHostIBuffer (and framesPerHostOBuffer)
|
||||
the default frameSize for the playback/recording pin.
|
||||
* ProcessingThread: Added a switch to only call PaUtil_EndBufferProcessing
|
||||
if the total input frames equals the total output frames
|
||||
|
||||
5th September 2004:
|
||||
This is the first public version of the code. It should be considered
|
||||
an alpha release with zero guarantee not to crash on any particular
|
||||
system. So far it has only been tested in the author's development
|
||||
environment, which means a Win2k/SP2 PIII laptop with integrated
|
||||
SoundMAX driver and USB Tascam US-428 compiled with both MinGW
|
||||
(GCC 3.3) and MSVC++6 using the MS DirectX 9 SDK.
|
||||
It has been most widely tested with the MinGW build, with most of the
|
||||
test programs (particularly paqa_devs and paqa_errs) passing.
|
||||
There are some notable failures: patest_out_underflow and both of the
|
||||
blocking I/O tests (as blocking I/O is not implemented).
|
||||
At this point the code needs to be tested with a much wider variety
|
||||
of configurations and feedback provided from testers regarding
|
||||
both working and failing cases.
|
||||
|
||||
What is the WDM-KS host API?
|
||||
----------------------------
|
||||
PortAudio for Windows currently has 3 functional host implementations.
|
||||
MME uses the oldest Windows audio API which does not offer good
|
||||
play/record latency.
|
||||
DirectX improves this, but still imposes a penalty
|
||||
of 10s of milliseconds due to the system mixing of streams from
|
||||
multiple applications.
|
||||
ASIO offers very good latency, but requires special drivers which are
|
||||
not always available for cheaper audio hardware. Also, when ASIO
|
||||
drivers are available, they are not always so robust because they
|
||||
bypass all of the standardised Windows device driver architecture
|
||||
and hit the hardware their own way.
|
||||
Alternatively there are a couple of free (but closed source) ASIO
|
||||
implementations which connect to the lower level Windows
|
||||
"Kernel Streaming" API, but again these require special installation
|
||||
by the user, and can be limited in functionality or difficult to use.
|
||||
|
||||
This is where the PortAudio "WDM-KS" host implementation comes in.
|
||||
It directly connects PortAudio to the same Kernel Streaming API which
|
||||
those ASIO bridges use. This avoids the mixing penatly of DirectX,
|
||||
giving at least as good latency as any ASIO driver, but it has the
|
||||
advantage of working with ANY Windows audio hardware which is available
|
||||
through the normal MME/DirectX routes without the user requiring
|
||||
any additional device drivers to be installed, and allowing all
|
||||
device selection to be done through the normal PortAudio API.
|
||||
|
||||
Note that in general you should only be using this host API if your
|
||||
application has a real requirement for very low latency audio (<20ms),
|
||||
either because you are generating sounds in real-time based upon
|
||||
user input, or you a processing recorded audio in real time.
|
||||
|
||||
The only thing to be aware of is that using the KS interface will
|
||||
block that device from being used by the rest of system through
|
||||
the higher level APIs, or conversely, if the system is using
|
||||
a device, the KS API will not be able to use it. MS recommend that
|
||||
you should keep the device open only when your application has focus.
|
||||
In PortAudio terms, this means having a stream Open on a WDMKS device.
|
||||
|
||||
Usage
|
||||
-----
|
||||
To add the WDMKS backend to your program which is already using
|
||||
PortAudio, you must undefine PA_NO_WDMKS from your build file,
|
||||
and include the pa_win_wdmks\pa_win_wdmks.c into your build.
|
||||
The file should compile in both C and C++.
|
||||
You will need a DirectX SDK installed on your system for the
|
||||
ks.h and ksmedia.h header files.
|
||||
You will need to link to the system "setupapi" library.
|
||||
Note that if you use MinGW, you will get more warnings from
|
||||
the DX header files when using GCC(C), and still a few warnings
|
||||
with G++(CPP).
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,160 +0,0 @@
|
||||
#ifndef PA_WIN_WMME_H
|
||||
#define PA_WIN_WMME_H
|
||||
/*
|
||||
* $Id$
|
||||
* PortAudio Portable Real-Time Audio Library
|
||||
* MME specific extensions
|
||||
*
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@brief WMME-specific PortAudio API extension header file.
|
||||
*/
|
||||
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#define paWinMmeUseLowLevelLatencyParameters (0x01)
|
||||
#define paWinMmeUseMultipleDevices (0x02) /* use mme specific multiple device feature */
|
||||
|
||||
|
||||
/* By default, the mme implementation drops the processing thread's priority
|
||||
to THREAD_PRIORITY_NORMAL and sleeps the thread if the CPU load exceeds 100%
|
||||
This flag disables any priority throttling. The processing thread will always
|
||||
run at THREAD_PRIORITY_TIME_CRITICAL.
|
||||
*/
|
||||
#define paWinMmeDontThrottleOverloadedProcessingThread (0x08)
|
||||
|
||||
|
||||
typedef struct PaWinMmeDeviceAndChannelCount{
|
||||
PaDeviceIndex device;
|
||||
int channelCount;
|
||||
}PaWinMmeDeviceAndChannelCount;
|
||||
|
||||
|
||||
typedef struct PaWinMmeStreamInfo{
|
||||
unsigned long size; /**< sizeof(PaWinMmeStreamInfo) */
|
||||
PaHostApiTypeId hostApiType; /**< paMME */
|
||||
unsigned long version; /**< 1 */
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
/* low-level latency setting support
|
||||
These settings control the number and size of host buffers in order
|
||||
to set latency. They will be used instead of the generic parameters
|
||||
to Pa_OpenStream() if flags contains the PaWinMmeUseLowLevelLatencyParameters
|
||||
flag.
|
||||
|
||||
If PaWinMmeStreamInfo structures with PaWinMmeUseLowLevelLatencyParameters
|
||||
are supplied for both input and output in a full duplex stream, then the
|
||||
input and output framesPerBuffer must be the same, or the larger of the
|
||||
two must be a multiple of the smaller, otherwise a
|
||||
paIncompatibleHostApiSpecificStreamInfo error will be returned from
|
||||
Pa_OpenStream().
|
||||
*/
|
||||
unsigned long framesPerBuffer;
|
||||
unsigned long bufferCount; /* formerly numBuffers */
|
||||
|
||||
/* multiple devices per direction support
|
||||
If flags contains the PaWinMmeUseMultipleDevices flag,
|
||||
this functionality will be used, otherwise the device parameter to
|
||||
Pa_OpenStream() will be used instead.
|
||||
If devices are specified here, the corresponding device parameter
|
||||
to Pa_OpenStream() should be set to paUseHostApiSpecificDeviceSpecification,
|
||||
otherwise an paInvalidDevice error will result.
|
||||
The total number of channels accross all specified devices
|
||||
must agree with the corresponding channelCount parameter to
|
||||
Pa_OpenStream() otherwise a paInvalidChannelCount error will result.
|
||||
*/
|
||||
PaWinMmeDeviceAndChannelCount *devices;
|
||||
unsigned long deviceCount;
|
||||
|
||||
}PaWinMmeStreamInfo;
|
||||
|
||||
|
||||
/** Retrieve the number of wave in handles used by a PortAudio WinMME stream.
|
||||
Returns zero if the stream is output only.
|
||||
|
||||
@return A non-negative value indicating the number of wave in handles
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
|
||||
@see PaWinMME_GetStreamInputHandle
|
||||
*/
|
||||
int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
|
||||
|
||||
|
||||
/** Retrieve a wave in handle used by a PortAudio WinMME stream.
|
||||
|
||||
@param stream The stream to query.
|
||||
@param handleIndex The zero based index of the wave in handle to retrieve. This
|
||||
should be in the range [0, PaWinMME_GetStreamInputHandle(stream)-1].
|
||||
|
||||
@return A valid wave in handle, or NULL if an error occurred.
|
||||
|
||||
@see PaWinMME_GetStreamInputHandle
|
||||
*/
|
||||
HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int handleIndex );
|
||||
|
||||
|
||||
/** Retrieve the number of wave out handles used by a PortAudio WinMME stream.
|
||||
Returns zero if the stream is input only.
|
||||
|
||||
@return A non-negative value indicating the number of wave out handles
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
|
||||
@see PaWinMME_GetStreamOutputHandle
|
||||
*/
|
||||
int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
|
||||
|
||||
|
||||
/** Retrieve a wave out handle used by a PortAudio WinMME stream.
|
||||
|
||||
@param stream The stream to query.
|
||||
@param handleIndex The zero based index of the wave out handle to retrieve.
|
||||
This should be in the range [0, PaWinMME_GetStreamOutputHandleCount(stream)-1].
|
||||
|
||||
@return A valid wave out handle, or NULL if an error occurred.
|
||||
|
||||
@see PaWinMME_GetStreamOutputHandleCount
|
||||
*/
|
||||
HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int handleIndex );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PA_WIN_WMME_H */
|
||||
Loading…
x
Reference in New Issue
Block a user