mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-12-16 07:53:24 -05:00
- Import of portaudio v19
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/trunk@189 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
019ece987d
commit
8d353a5b3b
65
portaudio-v19/LICENSE.txt
Normal file
65
portaudio-v19/LICENSE.txt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
Portable header file to contain:
|
||||||
|
/*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* PortAudio API Header File
|
||||||
|
* Latest version available at: 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Implementation files to contain:
|
||||||
|
/*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* Latest version at: http://www.audiomulch.com/portaudio/
|
||||||
|
* <platform> Implementation
|
||||||
|
* Copyright (c) 1999-2000 <author(s)>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
186
portaudio-v19/Makefile
Normal file
186
portaudio-v19/Makefile
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
# Generated automatically from Makefile.in by configure.
|
||||||
|
#
|
||||||
|
# PortAudio V19 Makefile.in
|
||||||
|
#
|
||||||
|
# Dominic Mazzoni
|
||||||
|
#
|
||||||
|
|
||||||
|
PREFIX = /usr/local
|
||||||
|
CC = cc
|
||||||
|
CFLAGS = -Ipa_common -g -O2 -Wall -pedantic -pipe -fPIC -DPA_LITTLE_ENDIAN -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DHAVE_LIBPTHREAD=1 -DPA_USE_OSS=1
|
||||||
|
LIBS = -lpthread -lm -lpthread
|
||||||
|
AR = /usr/bin/ar
|
||||||
|
RANLIB = ranlib
|
||||||
|
INSTALL = /usr/bin/install -c
|
||||||
|
SHARED_FLAGS = -shared -fPIC
|
||||||
|
DLL_LIBS =
|
||||||
|
CXXFLAGS =
|
||||||
|
NASM =
|
||||||
|
NASMOPT =
|
||||||
|
|
||||||
|
OTHER_OBJS = pa_unix_oss/pa_unix_oss.o pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o
|
||||||
|
|
||||||
|
PALIB = libportaudio.a
|
||||||
|
PADLL = libportaudio.so
|
||||||
|
PADLLV = $(PADLL).0.0.19
|
||||||
|
PAINC = pa_common/portaudio.h
|
||||||
|
|
||||||
|
COMMON_OBJS = \
|
||||||
|
pa_common/pa_allocation.o \
|
||||||
|
pa_common/pa_converters.o \
|
||||||
|
pa_common/pa_cpuload.o \
|
||||||
|
pa_common/pa_dither.o \
|
||||||
|
pa_common/pa_front.o \
|
||||||
|
pa_common/pa_process.o \
|
||||||
|
pa_common/pa_skeleton.o \
|
||||||
|
pa_common/pa_stream.o \
|
||||||
|
pa_common/pa_trace.o
|
||||||
|
|
||||||
|
TESTS = \
|
||||||
|
bin/paqa_devs \
|
||||||
|
bin/paqa_errs \
|
||||||
|
bin/patest1 \
|
||||||
|
bin/patest_buffer \
|
||||||
|
bin/patest_callbackstop \
|
||||||
|
bin/patest_clip \
|
||||||
|
bin/patest_dither \
|
||||||
|
bin/patest_hang \
|
||||||
|
bin/patest_in_overflow \
|
||||||
|
bin/patest_latency \
|
||||||
|
bin/patest_leftright \
|
||||||
|
bin/patest_longsine \
|
||||||
|
bin/patest_many \
|
||||||
|
bin/patest_maxsines \
|
||||||
|
bin/patest_multi_sine \
|
||||||
|
bin/patest_out_underflow \
|
||||||
|
bin/patest_pink \
|
||||||
|
bin/patest_prime \
|
||||||
|
bin/patest_read_record \
|
||||||
|
bin/patest_record \
|
||||||
|
bin/patest_ringmix \
|
||||||
|
bin/patest_saw \
|
||||||
|
bin/patest_sine8 \
|
||||||
|
bin/patest_sine \
|
||||||
|
bin/patest_sine_formats \
|
||||||
|
bin/patest_sine_time \
|
||||||
|
bin/patest_start_stop \
|
||||||
|
bin/patest_stop \
|
||||||
|
bin/patest_sync \
|
||||||
|
bin/patest_toomanysines \
|
||||||
|
bin/patest_underflow \
|
||||||
|
bin/patest_wire \
|
||||||
|
bin/patest_write_sine \
|
||||||
|
bin/pa_devs \
|
||||||
|
bin/pa_fuzz \
|
||||||
|
bin/pa_minlat
|
||||||
|
|
||||||
|
# Most of these don't compile yet. Put them in TESTS, above, if
|
||||||
|
# you want to try to compile them...
|
||||||
|
ALL_TESTS = \
|
||||||
|
bin/debug_convert \
|
||||||
|
bin/debug_dither_calc \
|
||||||
|
bin/debug_dual \
|
||||||
|
bin/debug_multi_in \
|
||||||
|
bin/debug_multi_out \
|
||||||
|
bin/debug_record \
|
||||||
|
bin/debug_record_reuse \
|
||||||
|
bin/debug_sine_amp \
|
||||||
|
bin/debug_sine \
|
||||||
|
bin/debug_sine_formats \
|
||||||
|
bin/debug_srate \
|
||||||
|
bin/debug_test1 \
|
||||||
|
bin/pa_devs \
|
||||||
|
bin/pa_fuzz \
|
||||||
|
bin/pa_minlat \
|
||||||
|
bin/paqa_devs \
|
||||||
|
bin/paqa_errs \
|
||||||
|
bin/patest1 \
|
||||||
|
bin/patest_buffer \
|
||||||
|
bin/patest_clip \
|
||||||
|
bin/patest_dither \
|
||||||
|
bin/patest_hang \
|
||||||
|
bin/patest_in_overflow \
|
||||||
|
bin/patest_latency \
|
||||||
|
bin/patest_leftright \
|
||||||
|
bin/patest_longsine \
|
||||||
|
bin/patest_many \
|
||||||
|
bin/patest_maxsines \
|
||||||
|
bin/patest_multi_sine \
|
||||||
|
bin/patest_out_underflow \
|
||||||
|
bin/patest_pink \
|
||||||
|
bin/patest_read_record \
|
||||||
|
bin/patest_record \
|
||||||
|
bin/patest_ringmix \
|
||||||
|
bin/patest_saw \
|
||||||
|
bin/patest_sine8 \
|
||||||
|
bin/patest_sine \
|
||||||
|
bin/patest_sine_formats \
|
||||||
|
bin/patest_sine_time \
|
||||||
|
bin/patest_start_stop \
|
||||||
|
bin/patest_stop \
|
||||||
|
bin/patest_sync \
|
||||||
|
bin/patest_toomanysines \
|
||||||
|
bin/patest_underflow \
|
||||||
|
bin/patest_wire \
|
||||||
|
bin/patest_write_sine
|
||||||
|
|
||||||
|
OBJS = $(COMMON_OBJS) $(OTHER_OBJS)
|
||||||
|
|
||||||
|
all: lib/$(PALIB) lib/$(PADLLV) tests
|
||||||
|
|
||||||
|
tests: bin/ $(TESTS)
|
||||||
|
|
||||||
|
lib/$(PALIB): lib/ $(OBJS) Makefile $(PAINC)
|
||||||
|
$(AR) ruv lib/$(PALIB) $(OBJS)
|
||||||
|
$(RANLIB) lib/$(PALIB)
|
||||||
|
|
||||||
|
lib/$(PADLLV): lib/ $(OBJS) Makefile $(PAINC)
|
||||||
|
$(CC) $(SHARED_FLAGS) -o lib/$(PADLLV) $(OBJS) $(DLL_LIBS)
|
||||||
|
|
||||||
|
$(TESTS): bin/%: lib/$(PALIB) Makefile $(PAINC) pa_tests/%.c
|
||||||
|
$(CC) -o $@ $(CFLAGS) pa_tests/$*.c lib/$(PALIB) $(LIBS)
|
||||||
|
|
||||||
|
install: lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
$(INSTALL) -d $(PREFIX)/lib
|
||||||
|
$(INSTALL) -m 644 lib/$(PADLLV) $(PREFIX)/lib/$(PADLLV)
|
||||||
|
$(INSTALL) -m 644 lib/$(PALIB) $(PREFIX)/lib/$(PALIB)
|
||||||
|
cd $(PREFIX)/lib && rm -f $(PADLL) && ln -s $(PADLLV) $(PADLL)
|
||||||
|
$(INSTALL) -d $(PREFIX)/include
|
||||||
|
$(INSTALL) -m 644 pa_common/portaudio.h $(PREFIX)/include/portaudio.h
|
||||||
|
@echo ""
|
||||||
|
@echo "------------------------------------------------------------"
|
||||||
|
@echo "PortAudio was successfully installed."
|
||||||
|
@echo ""
|
||||||
|
@echo "On some systems (e.g. Linux) you should run 'ldconfig' now"
|
||||||
|
@echo "to make the shared object available. You may also need to"
|
||||||
|
@echo "modify your LD_LIBRARY_PATH environment variable to include"
|
||||||
|
@echo "the directory $(PREFIX)/lib"
|
||||||
|
@echo "------------------------------------------------------------"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(PREFIX)/lib/$(PADLLV)
|
||||||
|
rm -f $(PREFIX)/lib/$(PALIB)
|
||||||
|
rm -f $(PREFIX)/lib/$(PADLL)
|
||||||
|
rm -f $(PREFIX)/include/portaudio.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) $(TESTS) lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
|
||||||
|
%.o: %.c Makefile $(PAINC)
|
||||||
|
$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.o: %.cpp Makefile $(PAINC)
|
||||||
|
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.o: %.asm
|
||||||
|
$(NASM) $(NASMOPT) -o $@ $<
|
||||||
|
|
||||||
|
bin:
|
||||||
|
mkdir bin
|
||||||
|
|
||||||
|
lib:
|
||||||
|
mkdir lib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
186
portaudio-v19/Makefile.bak
Normal file
186
portaudio-v19/Makefile.bak
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
# Generated automatically from Makefile.in by configure.
|
||||||
|
#
|
||||||
|
# PortAudio V19 Makefile.in
|
||||||
|
#
|
||||||
|
# Dominic Mazzoni
|
||||||
|
#
|
||||||
|
|
||||||
|
PREFIX = /usr/local
|
||||||
|
CC = cc
|
||||||
|
CFLAGS = -g -O2 -Wall -pedantic -pipe -fPIC -DPA_LITTLE_ENDIAN -I/usr/local/include -Ipa_common -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DHAVE_LIBPTHREAD=1 -DPA_USE_JACK=1 -DPA_USE_OSS=1
|
||||||
|
LIBS = -lpthread -pthread -L/usr/local/lib -ljack -lm -lpthread
|
||||||
|
AR = /usr/bin/ar
|
||||||
|
RANLIB = ranlib
|
||||||
|
INSTALL = /usr/bin/install -c -o root -g wheel
|
||||||
|
SHARED_FLAGS = -shared -fPIC
|
||||||
|
DLL_LIBS = -pthread -L/usr/local/lib -ljack
|
||||||
|
CXXFLAGS = -O2 -pipe
|
||||||
|
NASM =
|
||||||
|
NASMOPT =
|
||||||
|
|
||||||
|
OTHER_OBJS = pa_jack/pa_jack.o pa_unix_oss/pa_unix_oss.o pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o
|
||||||
|
|
||||||
|
PALIB = libportaudio.a
|
||||||
|
PADLL = libportaudio.so
|
||||||
|
PADLLV = $(PADLL).0.0.19
|
||||||
|
PAINC = pa_common/portaudio.h
|
||||||
|
|
||||||
|
COMMON_OBJS = \
|
||||||
|
pa_common/pa_allocation.o \
|
||||||
|
pa_common/pa_converters.o \
|
||||||
|
pa_common/pa_cpuload.o \
|
||||||
|
pa_common/pa_dither.o \
|
||||||
|
pa_common/pa_front.o \
|
||||||
|
pa_common/pa_process.o \
|
||||||
|
pa_common/pa_skeleton.o \
|
||||||
|
pa_common/pa_stream.o \
|
||||||
|
pa_common/pa_trace.o
|
||||||
|
|
||||||
|
TESTS = \
|
||||||
|
bin/paqa_devs \
|
||||||
|
bin/paqa_errs \
|
||||||
|
bin/patest1 \
|
||||||
|
bin/patest_buffer \
|
||||||
|
bin/patest_callbackstop \
|
||||||
|
bin/patest_clip \
|
||||||
|
bin/patest_dither \
|
||||||
|
bin/patest_hang \
|
||||||
|
bin/patest_in_overflow \
|
||||||
|
bin/patest_latency \
|
||||||
|
bin/patest_leftright \
|
||||||
|
bin/patest_longsine \
|
||||||
|
bin/patest_many \
|
||||||
|
bin/patest_maxsines \
|
||||||
|
bin/patest_multi_sine \
|
||||||
|
bin/patest_out_underflow \
|
||||||
|
bin/patest_pink \
|
||||||
|
bin/patest_prime \
|
||||||
|
bin/patest_read_record \
|
||||||
|
bin/patest_record \
|
||||||
|
bin/patest_ringmix \
|
||||||
|
bin/patest_saw \
|
||||||
|
bin/patest_sine8 \
|
||||||
|
bin/patest_sine \
|
||||||
|
bin/patest_sine_formats \
|
||||||
|
bin/patest_sine_time \
|
||||||
|
bin/patest_start_stop \
|
||||||
|
bin/patest_stop \
|
||||||
|
bin/patest_sync \
|
||||||
|
bin/patest_toomanysines \
|
||||||
|
bin/patest_underflow \
|
||||||
|
bin/patest_wire \
|
||||||
|
bin/patest_write_sine \
|
||||||
|
bin/pa_devs \
|
||||||
|
bin/pa_fuzz \
|
||||||
|
bin/pa_minlat
|
||||||
|
|
||||||
|
# Most of these don't compile yet. Put them in TESTS, above, if
|
||||||
|
# you want to try to compile them...
|
||||||
|
ALL_TESTS = \
|
||||||
|
bin/debug_convert \
|
||||||
|
bin/debug_dither_calc \
|
||||||
|
bin/debug_dual \
|
||||||
|
bin/debug_multi_in \
|
||||||
|
bin/debug_multi_out \
|
||||||
|
bin/debug_record \
|
||||||
|
bin/debug_record_reuse \
|
||||||
|
bin/debug_sine_amp \
|
||||||
|
bin/debug_sine \
|
||||||
|
bin/debug_sine_formats \
|
||||||
|
bin/debug_srate \
|
||||||
|
bin/debug_test1 \
|
||||||
|
bin/pa_devs \
|
||||||
|
bin/pa_fuzz \
|
||||||
|
bin/pa_minlat \
|
||||||
|
bin/paqa_devs \
|
||||||
|
bin/paqa_errs \
|
||||||
|
bin/patest1 \
|
||||||
|
bin/patest_buffer \
|
||||||
|
bin/patest_clip \
|
||||||
|
bin/patest_dither \
|
||||||
|
bin/patest_hang \
|
||||||
|
bin/patest_in_overflow \
|
||||||
|
bin/patest_latency \
|
||||||
|
bin/patest_leftright \
|
||||||
|
bin/patest_longsine \
|
||||||
|
bin/patest_many \
|
||||||
|
bin/patest_maxsines \
|
||||||
|
bin/patest_multi_sine \
|
||||||
|
bin/patest_out_underflow \
|
||||||
|
bin/patest_pink \
|
||||||
|
bin/patest_read_record \
|
||||||
|
bin/patest_record \
|
||||||
|
bin/patest_ringmix \
|
||||||
|
bin/patest_saw \
|
||||||
|
bin/patest_sine8 \
|
||||||
|
bin/patest_sine \
|
||||||
|
bin/patest_sine_formats \
|
||||||
|
bin/patest_sine_time \
|
||||||
|
bin/patest_start_stop \
|
||||||
|
bin/patest_stop \
|
||||||
|
bin/patest_sync \
|
||||||
|
bin/patest_toomanysines \
|
||||||
|
bin/patest_underflow \
|
||||||
|
bin/patest_wire \
|
||||||
|
bin/patest_write_sine
|
||||||
|
|
||||||
|
OBJS = $(COMMON_OBJS) $(OTHER_OBJS)
|
||||||
|
|
||||||
|
all: lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
|
||||||
|
tests: bin/ $(TESTS)
|
||||||
|
|
||||||
|
lib/$(PALIB): lib/ $(OBJS) Makefile $(PAINC)
|
||||||
|
$(AR) ruv lib/$(PALIB) $(OBJS)
|
||||||
|
$(RANLIB) lib/$(PALIB)
|
||||||
|
|
||||||
|
lib/$(PADLLV): lib/ $(OBJS) Makefile $(PAINC)
|
||||||
|
$(CC) $(SHARED_FLAGS) -o lib/$(PADLLV) $(OBJS) $(DLL_LIBS)
|
||||||
|
|
||||||
|
$(TESTS): bin/%: lib/$(PALIB) Makefile $(PAINC) pa_tests/%.c
|
||||||
|
$(CC) -o $@ $(CFLAGS) pa_tests/$*.c lib/$(PALIB) $(LIBS)
|
||||||
|
|
||||||
|
install: lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
$(INSTALL) -d $(PREFIX)/lib
|
||||||
|
$(INSTALL) -m 644 lib/$(PADLLV) $(PREFIX)/lib/$(PADLLV)
|
||||||
|
$(INSTALL) -m 644 lib/$(PALIB) $(PREFIX)/lib/$(PALIB)
|
||||||
|
cd $(PREFIX)/lib && rm -f $(PADLL) && ln -s $(PADLLV) $(PADLL)
|
||||||
|
$(INSTALL) -d $(PREFIX)/include
|
||||||
|
$(INSTALL) -m 644 pa_common/portaudio.h $(PREFIX)/include/portaudio.h
|
||||||
|
@echo ""
|
||||||
|
@echo "------------------------------------------------------------"
|
||||||
|
@echo "PortAudio was successfully installed."
|
||||||
|
@echo ""
|
||||||
|
@echo "On some systems (e.g. Linux) you should run 'ldconfig' now"
|
||||||
|
@echo "to make the shared object available. You may also need to"
|
||||||
|
@echo "modify your LD_LIBRARY_PATH environment variable to include"
|
||||||
|
@echo "the directory $(PREFIX)/lib"
|
||||||
|
@echo "------------------------------------------------------------"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(PREFIX)/lib/$(PADLLV)
|
||||||
|
rm -f $(PREFIX)/lib/$(PALIB)
|
||||||
|
rm -f $(PREFIX)/lib/$(PADLL)
|
||||||
|
rm -f $(PREFIX)/include/portaudio.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) $(TESTS) lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
|
||||||
|
%.o: %.c Makefile $(PAINC)
|
||||||
|
$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.o: %.cpp Makefile $(PAINC)
|
||||||
|
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.o: %.asm
|
||||||
|
$(NASM) $(NASMOPT) -o $@ $<
|
||||||
|
|
||||||
|
bin:
|
||||||
|
mkdir bin
|
||||||
|
|
||||||
|
lib:
|
||||||
|
mkdir lib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
185
portaudio-v19/Makefile.in
Normal file
185
portaudio-v19/Makefile.in
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#
|
||||||
|
# PortAudio V19 Makefile.in
|
||||||
|
#
|
||||||
|
# Dominic Mazzoni
|
||||||
|
#
|
||||||
|
|
||||||
|
PREFIX = @prefix@
|
||||||
|
CC = @CC@
|
||||||
|
CFLAGS = -Ipa_common @CFLAGS@ @DEFS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
AR = @AR@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
SHARED_FLAGS = @SHARED_FLAGS@
|
||||||
|
DLL_LIBS = @DLL_LIBS@
|
||||||
|
CXXFLAGS = @CXXFLAGS@
|
||||||
|
NASM = @NASM@
|
||||||
|
NASMOPT = @NASMOPT@
|
||||||
|
|
||||||
|
OTHER_OBJS = @OTHER_OBJS@
|
||||||
|
|
||||||
|
PALIB = libportaudio.a
|
||||||
|
PADLL = @PADLL@
|
||||||
|
PADLLV = $(PADLL).0.0.19
|
||||||
|
PAINC = pa_common/portaudio.h
|
||||||
|
|
||||||
|
COMMON_OBJS = \
|
||||||
|
pa_common/pa_allocation.o \
|
||||||
|
pa_common/pa_converters.o \
|
||||||
|
pa_common/pa_cpuload.o \
|
||||||
|
pa_common/pa_dither.o \
|
||||||
|
pa_common/pa_front.o \
|
||||||
|
pa_common/pa_process.o \
|
||||||
|
pa_common/pa_skeleton.o \
|
||||||
|
pa_common/pa_stream.o \
|
||||||
|
pa_common/pa_trace.o
|
||||||
|
|
||||||
|
TESTS = \
|
||||||
|
bin/paqa_devs \
|
||||||
|
bin/paqa_errs \
|
||||||
|
bin/patest1 \
|
||||||
|
bin/patest_buffer \
|
||||||
|
bin/patest_callbackstop \
|
||||||
|
bin/patest_clip \
|
||||||
|
bin/patest_dither \
|
||||||
|
bin/patest_hang \
|
||||||
|
bin/patest_in_overflow \
|
||||||
|
bin/patest_latency \
|
||||||
|
bin/patest_leftright \
|
||||||
|
bin/patest_longsine \
|
||||||
|
bin/patest_many \
|
||||||
|
bin/patest_maxsines \
|
||||||
|
bin/patest_multi_sine \
|
||||||
|
bin/patest_out_underflow \
|
||||||
|
bin/patest_pink \
|
||||||
|
bin/patest_prime \
|
||||||
|
bin/patest_read_record \
|
||||||
|
bin/patest_record \
|
||||||
|
bin/patest_ringmix \
|
||||||
|
bin/patest_saw \
|
||||||
|
bin/patest_sine8 \
|
||||||
|
bin/patest_sine \
|
||||||
|
bin/patest_sine_formats \
|
||||||
|
bin/patest_sine_time \
|
||||||
|
bin/patest_start_stop \
|
||||||
|
bin/patest_stop \
|
||||||
|
bin/patest_sync \
|
||||||
|
bin/patest_toomanysines \
|
||||||
|
bin/patest_underflow \
|
||||||
|
bin/patest_wire \
|
||||||
|
bin/patest_write_sine \
|
||||||
|
bin/pa_devs \
|
||||||
|
bin/pa_fuzz \
|
||||||
|
bin/pa_minlat
|
||||||
|
|
||||||
|
# Most of these don't compile yet. Put them in TESTS, above, if
|
||||||
|
# you want to try to compile them...
|
||||||
|
ALL_TESTS = \
|
||||||
|
bin/debug_convert \
|
||||||
|
bin/debug_dither_calc \
|
||||||
|
bin/debug_dual \
|
||||||
|
bin/debug_multi_in \
|
||||||
|
bin/debug_multi_out \
|
||||||
|
bin/debug_record \
|
||||||
|
bin/debug_record_reuse \
|
||||||
|
bin/debug_sine_amp \
|
||||||
|
bin/debug_sine \
|
||||||
|
bin/debug_sine_formats \
|
||||||
|
bin/debug_srate \
|
||||||
|
bin/debug_test1 \
|
||||||
|
bin/pa_devs \
|
||||||
|
bin/pa_fuzz \
|
||||||
|
bin/pa_minlat \
|
||||||
|
bin/paqa_devs \
|
||||||
|
bin/paqa_errs \
|
||||||
|
bin/patest1 \
|
||||||
|
bin/patest_buffer \
|
||||||
|
bin/patest_clip \
|
||||||
|
bin/patest_dither \
|
||||||
|
bin/patest_hang \
|
||||||
|
bin/patest_in_overflow \
|
||||||
|
bin/patest_latency \
|
||||||
|
bin/patest_leftright \
|
||||||
|
bin/patest_longsine \
|
||||||
|
bin/patest_many \
|
||||||
|
bin/patest_maxsines \
|
||||||
|
bin/patest_multi_sine \
|
||||||
|
bin/patest_out_underflow \
|
||||||
|
bin/patest_pink \
|
||||||
|
bin/patest_read_record \
|
||||||
|
bin/patest_record \
|
||||||
|
bin/patest_ringmix \
|
||||||
|
bin/patest_saw \
|
||||||
|
bin/patest_sine8 \
|
||||||
|
bin/patest_sine \
|
||||||
|
bin/patest_sine_formats \
|
||||||
|
bin/patest_sine_time \
|
||||||
|
bin/patest_start_stop \
|
||||||
|
bin/patest_stop \
|
||||||
|
bin/patest_sync \
|
||||||
|
bin/patest_toomanysines \
|
||||||
|
bin/patest_underflow \
|
||||||
|
bin/patest_wire \
|
||||||
|
bin/patest_write_sine
|
||||||
|
|
||||||
|
OBJS = $(COMMON_OBJS) $(OTHER_OBJS)
|
||||||
|
|
||||||
|
all: lib/$(PALIB) lib/$(PADLLV) tests
|
||||||
|
|
||||||
|
tests: bin/ $(TESTS)
|
||||||
|
|
||||||
|
lib/$(PALIB): lib/ $(OBJS) Makefile $(PAINC)
|
||||||
|
$(AR) ruv lib/$(PALIB) $(OBJS)
|
||||||
|
$(RANLIB) lib/$(PALIB)
|
||||||
|
|
||||||
|
lib/$(PADLLV): lib/ $(OBJS) Makefile $(PAINC)
|
||||||
|
$(CC) $(SHARED_FLAGS) -o lib/$(PADLLV) $(OBJS) $(DLL_LIBS)
|
||||||
|
|
||||||
|
$(TESTS): bin/%: lib/$(PALIB) Makefile $(PAINC) pa_tests/%.c
|
||||||
|
$(CC) -o $@ $(CFLAGS) pa_tests/$*.c lib/$(PALIB) $(LIBS)
|
||||||
|
|
||||||
|
install: lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
$(INSTALL) -d $(PREFIX)/lib
|
||||||
|
$(INSTALL) -m 644 lib/$(PADLLV) $(PREFIX)/lib/$(PADLLV)
|
||||||
|
$(INSTALL) -m 644 lib/$(PALIB) $(PREFIX)/lib/$(PALIB)
|
||||||
|
cd $(PREFIX)/lib && rm -f $(PADLL) && ln -s $(PADLLV) $(PADLL)
|
||||||
|
$(INSTALL) -d $(PREFIX)/include
|
||||||
|
$(INSTALL) -m 644 pa_common/portaudio.h $(PREFIX)/include/portaudio.h
|
||||||
|
@echo ""
|
||||||
|
@echo "------------------------------------------------------------"
|
||||||
|
@echo "PortAudio was successfully installed."
|
||||||
|
@echo ""
|
||||||
|
@echo "On some systems (e.g. Linux) you should run 'ldconfig' now"
|
||||||
|
@echo "to make the shared object available. You may also need to"
|
||||||
|
@echo "modify your LD_LIBRARY_PATH environment variable to include"
|
||||||
|
@echo "the directory $(PREFIX)/lib"
|
||||||
|
@echo "------------------------------------------------------------"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(PREFIX)/lib/$(PADLLV)
|
||||||
|
rm -f $(PREFIX)/lib/$(PALIB)
|
||||||
|
rm -f $(PREFIX)/lib/$(PADLL)
|
||||||
|
rm -f $(PREFIX)/include/portaudio.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) $(TESTS) lib/$(PALIB) lib/$(PADLLV)
|
||||||
|
|
||||||
|
%.o: %.c Makefile $(PAINC)
|
||||||
|
$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.o: %.cpp Makefile $(PAINC)
|
||||||
|
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.o: %.asm
|
||||||
|
$(NASM) $(NASMOPT) -o $@ $<
|
||||||
|
|
||||||
|
bin:
|
||||||
|
mkdir bin
|
||||||
|
|
||||||
|
lib:
|
||||||
|
mkdir lib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
81
portaudio-v19/README.txt
Normal file
81
portaudio-v19/README.txt
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
README for PortAudio
|
||||||
|
Implementations for PC DirectSound and Mac SoundManager
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* Latest Version at: http://www.portaudio.com//
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2000 Phil Burk and Ross Bencina
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
PortAudio is a portable audio I/O library designed for cross-platform
|
||||||
|
support of audio. It uses a callback mechanism to request audio processing.
|
||||||
|
Audio can be generated in various formats, including 32 bit floating point,
|
||||||
|
and will be converted to the native format internally.
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
See "pa_common/portaudio.h" for API spec.
|
||||||
|
See docs folder for a tutorial.
|
||||||
|
Also see http://www.portaudio.com/docs/
|
||||||
|
And see "pa_tests/patest_saw.c" for an example.
|
||||||
|
|
||||||
|
For information on compiling programs with PortAudio, please see the
|
||||||
|
tutorial at:
|
||||||
|
|
||||||
|
http://www.portaudio.com/docs/pa_tutorial.html
|
||||||
|
|
||||||
|
Important Files and Folders:
|
||||||
|
pa_common/ = platform independant code
|
||||||
|
pa_common/portaudio.h = header file for PortAudio API. Specifies API.
|
||||||
|
pa_common/pa_lib.c = host independant code for all implementations.
|
||||||
|
|
||||||
|
pablio = simple blocking read/write interface
|
||||||
|
|
||||||
|
Platform Implementations
|
||||||
|
pa_asio = ASIO for Windows and Macintosh
|
||||||
|
pa_beos = BeOS
|
||||||
|
pa_mac_sm = Macintosh Sound Manager for OS 8,9 and Carbon
|
||||||
|
pa_mac_core = Macintosh Core Audio for OS X
|
||||||
|
pa_sgi = Silicon Graphics AL
|
||||||
|
pa_unix_oss = OSS implementation for various Unixes
|
||||||
|
pa_win_ds = Windows Direct Sound
|
||||||
|
pa_win_wmme = Windows MME (most widely supported)
|
||||||
|
|
||||||
|
Test Programs
|
||||||
|
pa_tests/pa_fuzz.c = guitar fuzz box
|
||||||
|
pa_tests/pa_devs.c = print a list of available devices
|
||||||
|
pa_tests/pa_minlat.c = determine minimum latency for your machine
|
||||||
|
pa_tests/paqa_devs.c = self test that opens all devices
|
||||||
|
pa_tests/paqa_errs.c = test error detection and reporting
|
||||||
|
pa_tests/patest_clip.c = hear a sine wave clipped and unclipped
|
||||||
|
pa_tests/patest_dither.c = hear effects of dithering (extremely subtle)
|
||||||
|
pa_tests/patest_pink.c = fun with pink noise
|
||||||
|
pa_tests/patest_record.c = record and playback some audio
|
||||||
|
pa_tests/patest_maxsines.c = how many sine waves can we play? Tests Pa_GetCPULoad().
|
||||||
|
pa_tests/patest_sine.c = output a sine wave in a simple PA app
|
||||||
|
pa_tests/patest_sync.c = test syncronization of audio and video
|
||||||
|
pa_tests/patest_wire.c = pass input to output, wire simulator
|
||||||
198
portaudio-v19/SConscript
Normal file
198
portaudio-v19/SConscript
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import os.path, copy, sys
|
||||||
|
|
||||||
|
def checkSymbol(conf, header, library=None, symbol=None, autoadd=True, critical=False, pkgName=None):
|
||||||
|
env = conf.env
|
||||||
|
if library is None:
|
||||||
|
library = "c" # Standard library
|
||||||
|
autoadd = False
|
||||||
|
|
||||||
|
if pkgName is not None:
|
||||||
|
origLibPath = copy.copy(env.get("LIBPATH", None))
|
||||||
|
origLibs = copy.copy(env.get("LIBS", None))
|
||||||
|
origLinkFlags = copy.copy(env.get("LINKFLAGS", None))
|
||||||
|
origCppFlags = copy.copy(env.get("CPPFLAGS", None))
|
||||||
|
origCppPath = copy.copy(env.get("CPPPATH", None))
|
||||||
|
origCcFlags = copy.copy(env.get("CCFLAGS", None))
|
||||||
|
origAsFlags = copy.copy(env.get("ASFLAGS", None))
|
||||||
|
|
||||||
|
try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName)
|
||||||
|
except: pass
|
||||||
|
else:
|
||||||
|
# I see no other way of checking that the parsing succeeded, if it did add no more linking parameters
|
||||||
|
if env["LIBS"] != origLibs:
|
||||||
|
autoadd = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not conf.CheckCHeader(header, include_quotes="<>"):
|
||||||
|
raise ConfigurationError("missing header %s" % header)
|
||||||
|
if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoadd):
|
||||||
|
raise ConfigurationError("missing symbol %s in library %s" % (symbol, library))
|
||||||
|
except ConfigurationError:
|
||||||
|
if pkgName is not None:
|
||||||
|
# Restore any changes made by ParseConfig
|
||||||
|
if origLibPath is not None:
|
||||||
|
env["LIBPATH"] = origLibPath
|
||||||
|
if origLibs is not None:
|
||||||
|
env["LIBS"] = origLibs
|
||||||
|
if origLinkFlags is not None:
|
||||||
|
env["LINKFLAGS"] = origLinkFlags
|
||||||
|
if origCppFlags is not None:
|
||||||
|
env["CPPFLAGS"] = origCppFlags
|
||||||
|
if origCppPath is not None:
|
||||||
|
env["CPPPATH"] = origCppPath
|
||||||
|
if origCcFlags is not None:
|
||||||
|
env["CCFLAGS"] = origCcFlags
|
||||||
|
if origAsFlags is not None:
|
||||||
|
env["ASFLAGS"] = origAsFlags
|
||||||
|
|
||||||
|
if not critical:
|
||||||
|
return False
|
||||||
|
raise
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
Import("env", "Platform", "Posix", "ConfigurationError")
|
||||||
|
|
||||||
|
# Store all signatures in one file, otherwise .sconsign files will get installed along with our own files
|
||||||
|
env.SConsignFile()
|
||||||
|
|
||||||
|
neededLibs = []
|
||||||
|
optionalImpls = {}
|
||||||
|
if Platform in Posix:
|
||||||
|
neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")]
|
||||||
|
if env["useALSA"]:
|
||||||
|
optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open")
|
||||||
|
if env["useJACK"]:
|
||||||
|
optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new")
|
||||||
|
if env["useOSS"]:
|
||||||
|
# TODO: It looks like the prefix for soundcard.h depends on the platform
|
||||||
|
optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None)
|
||||||
|
else:
|
||||||
|
raise ConfigurationError("unknown platform %s" % Platform)
|
||||||
|
|
||||||
|
if Platform == "darwin":
|
||||||
|
env.Append(LINKFLAGS=["-framework CoreAudio", "-framework AudioToolBox"])
|
||||||
|
env.Append(CPPDEFINES=["PA_USE_COREAUDIO"])
|
||||||
|
elif Platform == "cygwin":
|
||||||
|
env.Append(LIBS=["winmm"])
|
||||||
|
elif Platform == "irix":
|
||||||
|
neededLibs += [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")]
|
||||||
|
env.Append(CPPDEFINES=["PA_USE_SGI"])
|
||||||
|
|
||||||
|
def CheckCTypeSize(context, tp):
|
||||||
|
context.Message("Checking the size of C type %s..." % tp)
|
||||||
|
ret = context.TryRun("""
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("%%d", sizeof(%s));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
""" % tp, ".c")
|
||||||
|
if not ret[0]:
|
||||||
|
context.Result(" Couldn't obtain size of type %s!" % tp)
|
||||||
|
return None
|
||||||
|
|
||||||
|
assert ret[1]
|
||||||
|
sz = int(ret[1])
|
||||||
|
context.Result("%d" % sz)
|
||||||
|
return sz
|
||||||
|
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"])
|
||||||
|
elif sys.byteorder == "big":
|
||||||
|
env.Append(CPPDEFINES=["PA_BIG_ENDIAN"])
|
||||||
|
else:
|
||||||
|
raise ConfigurationError("unknown byte order: %s" % sys.byteorder)
|
||||||
|
if env["enableDebugOutput"]:
|
||||||
|
env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"])
|
||||||
|
|
||||||
|
# Start configuration
|
||||||
|
|
||||||
|
conf = env.Configure(log_file="sconf.log", custom_tests={"CheckCTypeSize": CheckCTypeSize})
|
||||||
|
env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")])
|
||||||
|
env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")])
|
||||||
|
env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")])
|
||||||
|
if checkSymbol(conf, "time.h", "rt", "clock_gettime"):
|
||||||
|
env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"])
|
||||||
|
if checkSymbol(conf, "time.h", "nanosleep"):
|
||||||
|
env.Append(CPPDEFINES=["HAVE_NANOSLEEP"])
|
||||||
|
|
||||||
|
for lib, hdr, sym in neededLibs:
|
||||||
|
checkSymbol(conf, hdr, lib, sym, critical=True)
|
||||||
|
for name, val in optionalImpls.items():
|
||||||
|
lib, hdr, sym = val
|
||||||
|
if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()):
|
||||||
|
env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()])
|
||||||
|
|
||||||
|
# Configuration finished
|
||||||
|
env = conf.Finish()
|
||||||
|
|
||||||
|
CommonSources = [os.path.join("pa_common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \
|
||||||
|
pa_process.c pa_skeleton.c pa_stream.c pa_trace.c".split()]
|
||||||
|
|
||||||
|
ImplSources = []
|
||||||
|
if Platform in Posix:
|
||||||
|
env.AppendUnique(LINKFLAGS=["-pthread"])
|
||||||
|
BaseCFlags = "-Wall -pedantic -pipe -pthread"
|
||||||
|
DebugCFlags = "-g"
|
||||||
|
OptCFlags = "-O2"
|
||||||
|
ImplSources += [os.path.join("pa_unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()]
|
||||||
|
|
||||||
|
if "ALSA" in optionalImpls:
|
||||||
|
ImplSources.append(os.path.join("pa_linux_alsa", "pa_linux_alsa.c"))
|
||||||
|
if "JACK" in optionalImpls:
|
||||||
|
ImplSources.append(os.path.join("pa_jack", "pa_jack.c"))
|
||||||
|
if "OSS" in optionalImpls:
|
||||||
|
ImplSources.append(os.path.join("pa_unix_oss", "pa_unix_oss.c"))
|
||||||
|
|
||||||
|
env["CCFLAGS"] = BaseCFlags
|
||||||
|
if env["enableDebug"]:
|
||||||
|
env["CCFLAGS"] += " " + DebugCFlags
|
||||||
|
if env["enableOptimize"]:
|
||||||
|
env["CCFLAGS"] += " " + OptCFlags
|
||||||
|
if not env["enableAsserts"]:
|
||||||
|
env.Append(CPPDEFINES=["-DNDEBUG"])
|
||||||
|
if env["customCFlags"]:
|
||||||
|
env["CCFLAGS"] += " " + env["customCFlags"]
|
||||||
|
|
||||||
|
sources = CommonSources + ImplSources
|
||||||
|
|
||||||
|
if env["enableShared"]:
|
||||||
|
sharedLib = env.SharedLibrary(target="portaudio", source=sources)
|
||||||
|
else:
|
||||||
|
sharedLib = None
|
||||||
|
staticLib = env.StaticLibrary(target="portaudio", source=sources)
|
||||||
|
|
||||||
|
if Platform in Posix:
|
||||||
|
prefix = env["prefix"]
|
||||||
|
env.Alias("install", env.Install(os.path.join(prefix, "include"), os.path.join("pa_common", "portaudio.h")))
|
||||||
|
|
||||||
|
if env["enableStatic"]:
|
||||||
|
env.Alias("install", env.Install(os.path.join(prefix, "lib"), staticLib))
|
||||||
|
|
||||||
|
def symlink(env, target, source):
|
||||||
|
trgt = str(target[0])
|
||||||
|
src = str(source[0])
|
||||||
|
print trgt, src
|
||||||
|
|
||||||
|
if os.path.exists(trgt):
|
||||||
|
os.remove(trgt)
|
||||||
|
os.symlink("libportaudio.so.0.0.19", trgt)
|
||||||
|
if env["enableShared"]:
|
||||||
|
env.Alias("install", env.InstallAs(target=os.path.join(prefix, "lib", "%s.0.0.19") % sharedLib[0], source=sharedLib))
|
||||||
|
env.Alias("install", env.Command(os.path.join(prefix, "lib", "libportaudio.so"), sharedLib, symlink))
|
||||||
|
|
||||||
|
testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \
|
||||||
|
"patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \
|
||||||
|
"patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \
|
||||||
|
"patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \
|
||||||
|
"patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", \
|
||||||
|
"patest_toomanysines", "patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat"]
|
||||||
|
|
||||||
|
# The test directory ("bin") should be in the top-level PA directory, the calling script should ensure that SCons doesn't
|
||||||
|
# switch current directory by calling SConscriptChdir(False). Specifying an absolute directory for each target means it won't
|
||||||
|
# be relative to the build directory
|
||||||
|
tests = [env.Program(target=os.path.join(os.getcwd(), "bin", name), source=[os.path.join("pa_tests", name + ".c"), staticLib]) for name in testNames]
|
||||||
|
|
||||||
|
Return("sources", "sharedLib", "staticLib")
|
||||||
78
portaudio-v19/SConstruct
Normal file
78
portaudio-v19/SConstruct
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import sys, os.path
|
||||||
|
|
||||||
|
class ConfigurationError(Exception):
|
||||||
|
def __init__(self, reason):
|
||||||
|
Exception.__init__(self, "Configuration failed: %s" % reason)
|
||||||
|
|
||||||
|
def _PackageOption(pkgName, default="yes"):
|
||||||
|
return BoolOption("use%s" % pkgName[0].upper() + pkgName[1:], "use %s if available" % (pkgName), default)
|
||||||
|
|
||||||
|
def _BoolOption(opt, explanation, default="yes"):
|
||||||
|
return BoolOption("enable%s" % opt[0].upper() + opt[1:], explanation, default)
|
||||||
|
|
||||||
|
def _DirectoryOption(path, help, default):
|
||||||
|
return PathOption(path, help, default)
|
||||||
|
# Incompatible with the latest stable SCons
|
||||||
|
# return PathOption(path, help, default, PathOption.PathIsDir)
|
||||||
|
|
||||||
|
def _EnumOption(opt, explanation, allowedValues, default):
|
||||||
|
assert default in allowedValues
|
||||||
|
return EnumOption("with%s" % opt[0].upper() + opt[1:], explanation, default, allowed_values=allowedValues)
|
||||||
|
|
||||||
|
def getPlatform():
|
||||||
|
global __platform
|
||||||
|
try: return __platform
|
||||||
|
except NameError:
|
||||||
|
env = Environment()
|
||||||
|
if env["PLATFORM"] == "posix":
|
||||||
|
if sys.platform[:5] == "linux":
|
||||||
|
__platform = "linux"
|
||||||
|
else:
|
||||||
|
raise ConfigurationError("Unknown platform %s" % sys.platform)
|
||||||
|
else:
|
||||||
|
if not env["PLATFORM"] in ("win32", "cygwin") + Posix:
|
||||||
|
raise ConfigurationError("Unknown platform %s" % env["PLATFORM"])
|
||||||
|
__platform = env["PLATFORM"]
|
||||||
|
|
||||||
|
return __platform
|
||||||
|
|
||||||
|
# sunos, aix, hpux, irix, sunos appear to be platforms known by SCons, assuming they're POSIX compliant
|
||||||
|
Posix = ("linux", "darwin", "sunos", "aix", "hpux", "irix", "sunos")
|
||||||
|
Windows = ("win32", "cygwin")
|
||||||
|
env = Environment(CPPPATH="pa_common")
|
||||||
|
|
||||||
|
Platform = getPlatform()
|
||||||
|
|
||||||
|
opts = Options("options.cache", args=ARGUMENTS)
|
||||||
|
if Platform in Posix:
|
||||||
|
opts.AddOptions(
|
||||||
|
_DirectoryOption("prefix", "installation prefix", "/usr/local"),
|
||||||
|
_PackageOption("ALSA"),
|
||||||
|
_PackageOption("OSS"),
|
||||||
|
_PackageOption("JACK"),
|
||||||
|
)
|
||||||
|
elif Platform in Windows:
|
||||||
|
if Platform == "cygwin":
|
||||||
|
opts.AddOptions(_DirectoryOption("prefix", "installation prefix", "/usr/local"))
|
||||||
|
opts.AddOptions(_EnumOption("winAPI", "Windows API to use", ("wmme", "directx", "asio"), "wmme"))
|
||||||
|
|
||||||
|
if Platform == "darwin":
|
||||||
|
opts.AddOptions(_EnumOption("macAPI", "Mac API to use", ("asio", "core", "sm"), "core"))
|
||||||
|
|
||||||
|
opts.AddOptions(
|
||||||
|
_BoolOption("shared", "create shared library"),
|
||||||
|
_BoolOption("static", "create static library"),
|
||||||
|
_BoolOption("debug", "compile with debug symbols"),
|
||||||
|
_BoolOption("optimize", "compile with optimization", default="no"),
|
||||||
|
_BoolOption("asserts", "runtime assertions are helpful for debugging, but can be detrimental to performance", default="yes"),
|
||||||
|
_BoolOption("debugOutput", "enable debug output", default="no"),
|
||||||
|
("customCFlags", "customize compilation of C code", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
opts.Update(env)
|
||||||
|
opts.Save("options.cache", env)
|
||||||
|
|
||||||
|
Help(opts.GenerateHelpText(env))
|
||||||
|
|
||||||
|
env.SConscriptChdir(False)
|
||||||
|
SConscript("SConscript", build_dir=".build_scons", exports=["env", "Platform", "Posix", "ConfigurationError"], duplicate=False)
|
||||||
222
portaudio-v19/V19-devel-readme.txt
Normal file
222
portaudio-v19/V19-devel-readme.txt
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
STATUS:
|
||||||
|
|
||||||
|
MME, DirectSound and ASIO versions are more-or-less working. See FIXMEs @todos
|
||||||
|
and the proposals matrix at portaudio.com for further status.
|
||||||
|
|
||||||
|
The pa_tests directory contains tests. pa_tests/README.txt notes which tests
|
||||||
|
currently build.
|
||||||
|
|
||||||
|
The PaUtil support code is finished enough for other implementations to be
|
||||||
|
ported. No changes are expected to be made to the definition of the PaUtil
|
||||||
|
functions.
|
||||||
|
|
||||||
|
Note that it's not yet 100% clear how the current support functions
|
||||||
|
will interact with blocking read/write streams.
|
||||||
|
|
||||||
|
BUILD INSTRUCTIONS
|
||||||
|
|
||||||
|
to build tests/patest_sine.c you will need to compile and link the following
|
||||||
|
files (MME)
|
||||||
|
pa_common\pa_process.c
|
||||||
|
pa_common\pa_skeleton.c
|
||||||
|
pa_common\pa_stream.c
|
||||||
|
pa_common\pa_trace.c
|
||||||
|
pa_common\pa_converters.c
|
||||||
|
pa_common\pa_cpuload.c
|
||||||
|
pa_common\pa_dither.c
|
||||||
|
pa_common\pa_front.c
|
||||||
|
pa_common\pa_allocation.h
|
||||||
|
pa_win\pa_win_util.c
|
||||||
|
pa_win\pa_win_hostapis.c
|
||||||
|
pa_win_wmme\pa_win_wmme.c
|
||||||
|
|
||||||
|
see below for a description of these files.
|
||||||
|
|
||||||
|
|
||||||
|
FILES:
|
||||||
|
|
||||||
|
portaudio.h
|
||||||
|
public api header file
|
||||||
|
|
||||||
|
pa_front.c
|
||||||
|
implements the interface defined in portaudio.h. manages multiple host apis.
|
||||||
|
validates function parameters before calling through to host apis. tracks
|
||||||
|
open streams and closes them at Pa_Terminate().
|
||||||
|
|
||||||
|
pa_util.h
|
||||||
|
declares utility functions for use my implementations. including utility
|
||||||
|
functions which must be implemented separately for each platform.
|
||||||
|
|
||||||
|
pa_hostapi.h
|
||||||
|
hostapi representation structure used to interface between pa_front.c
|
||||||
|
and implementations
|
||||||
|
|
||||||
|
pa_stream.c/h
|
||||||
|
stream interface and representation structures and helper functions
|
||||||
|
used to interface between pa_front.c and implementations
|
||||||
|
|
||||||
|
pa_cpuload.c/h
|
||||||
|
source and header for cpu load calculation facility
|
||||||
|
|
||||||
|
pa_trace.c/h
|
||||||
|
source and header for debug trace log facility
|
||||||
|
|
||||||
|
pa_converters.c/h
|
||||||
|
sample buffer conversion facility
|
||||||
|
|
||||||
|
pa_dither.c/h
|
||||||
|
dither noise generator
|
||||||
|
|
||||||
|
pa_process.c/h
|
||||||
|
callback buffer processing facility including interleave and block adaption
|
||||||
|
|
||||||
|
pa_allocation.c/h
|
||||||
|
allocation context for tracking groups of allocations
|
||||||
|
|
||||||
|
pa_skeleton.c
|
||||||
|
an skeleton implementation showing how the common code can be used.
|
||||||
|
|
||||||
|
pa_win_util.c
|
||||||
|
Win32 implementation of platform specific PaUtil functions (memory allocation,
|
||||||
|
usec clock, Pa_Sleep().) The file will be used with all Win32 host APIs.
|
||||||
|
|
||||||
|
pa_win_hostapis.c
|
||||||
|
contains the paHostApiInitializers array and an implementation of
|
||||||
|
Pa_GetDefaultHostApi() for win32 builds.
|
||||||
|
|
||||||
|
pa_win_wmme.c
|
||||||
|
Win32 host api implementation for the windows multimedia extensions audio API.
|
||||||
|
|
||||||
|
pa_win_wmme.h
|
||||||
|
public header file containing interfaces to mme-specific functions and the
|
||||||
|
deviceInfo data structure.
|
||||||
|
|
||||||
|
|
||||||
|
CODING GUIDELINES:
|
||||||
|
|
||||||
|
naming conventions:
|
||||||
|
#defines begin with PA_
|
||||||
|
#defines local to a file end with _
|
||||||
|
global utility variables begin with paUtil
|
||||||
|
global utility types begin with PaUtil (including function types)
|
||||||
|
global utility functions begin with PaUtil_
|
||||||
|
static variables end with _
|
||||||
|
static constants begin with const and end with _
|
||||||
|
static funtions have no special prefix/suffix
|
||||||
|
|
||||||
|
In general, implementations should declare all of their members static,
|
||||||
|
except for their initializer which should be exported. All exported names
|
||||||
|
should be preceeded by Pa<MN>_ where MN is the module name, for example
|
||||||
|
the windows mme initializer should be named PaWinWmme_Initialize().
|
||||||
|
|
||||||
|
Every host api should define an initializer which returns an error code
|
||||||
|
and a PaHostApiInterface*. The initializer should only return an error other
|
||||||
|
than paNoError if it encounters an unexpected and fatal error (memory allocation
|
||||||
|
error for example). In general, there may be conditions under which it returns
|
||||||
|
a NULL interface pointer and also returns paNoError. For example, if the ASIO
|
||||||
|
implementation detects that ASIO is not installed, it should return a
|
||||||
|
NULL interface, and paNoError.
|
||||||
|
|
||||||
|
Platform-specific shared functions should begin with Pa<PN>_ where PN is the
|
||||||
|
platform name. eg. PaWin_ for windows, PaUnix_ for unix.
|
||||||
|
|
||||||
|
The above two conventions should also be followed whenever it is necessary to
|
||||||
|
share functions accross multiple source files.
|
||||||
|
|
||||||
|
Two utilities for debug messages are provided. The PA_DEBUG macro defined in
|
||||||
|
pa_implementation.h provides a simple way to print debug messages to stderr.
|
||||||
|
Due to real-time performance issues, PA_DEBUG may not be suitable for use
|
||||||
|
within the portaudio processing callback, or in other threads. In such cases
|
||||||
|
the event tracing facility provided in pa_trace.h may be more appropriate.
|
||||||
|
|
||||||
|
If PA_LOG_API_CALLS is defined, all calls to the public PortAudio API
|
||||||
|
will be logged to stderr along with parameter and return values.
|
||||||
|
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
(this list is totally out of date)
|
||||||
|
|
||||||
|
finish coding converter functions in pa_converters.c (anyone?)
|
||||||
|
|
||||||
|
implement block adaption in pa_process.c (phil?)
|
||||||
|
|
||||||
|
fix all current tests to work with new code. this should mostly involve
|
||||||
|
changing PortAudioStream to PaStream, and GetDefaultDeviceID to GetDefaultDevice etc.
|
||||||
|
|
||||||
|
write some new tests to exercise the multi-api functions
|
||||||
|
|
||||||
|
write (doxygen) documentation for pa_trace (phil?)
|
||||||
|
|
||||||
|
remove unused typeids from PaHostAPITypeID
|
||||||
|
|
||||||
|
create a global configuration file which documents which PA_ defines can be
|
||||||
|
used for configuration
|
||||||
|
|
||||||
|
need a coding standard for comment formatting
|
||||||
|
|
||||||
|
migrate directx (phil)
|
||||||
|
|
||||||
|
migrate asio (ross?, stephane?)
|
||||||
|
|
||||||
|
see top of pa_win_wmme.c for MME todo items (ross)
|
||||||
|
|
||||||
|
write style guide document (ross)
|
||||||
|
|
||||||
|
|
||||||
|
DESIGN ISSUES:
|
||||||
|
(this list is totally out of date)
|
||||||
|
|
||||||
|
consider removing Pa_ConvertHostApiDeviceIndexToGlobalDeviceIndex() from the API
|
||||||
|
|
||||||
|
switch to new latency parameter mechanism now (?)
|
||||||
|
|
||||||
|
question: if input or outputDriverInfo structures are passed for a different
|
||||||
|
hostApi from the one being called, do we return an error or just ignore
|
||||||
|
them? (i think return error)
|
||||||
|
|
||||||
|
consider renaming PortAudioCallback to PaStreamCallback
|
||||||
|
|
||||||
|
consider renaming PaError, PaResult
|
||||||
|
|
||||||
|
|
||||||
|
ASSORTED DISORGANISED NOTES:
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
pa_lib.c performs the following validations for Pa_OpenStream() which we do not currently do:
|
||||||
|
- checks the device info to make sure that the device supports the requested sample rate,
|
||||||
|
it may also change the sample rate to the "closest available" sample rate if it
|
||||||
|
is within a particular error margin
|
||||||
|
|
||||||
|
rationale for breaking up internalPortAudioStream:
|
||||||
|
each implementation has its own requirements and behavior, and should be
|
||||||
|
able to choose the best way to operate without being limited by the
|
||||||
|
constraints imposed by a common infrastructure. in other words the
|
||||||
|
implementations should be able to pick and choose services from the
|
||||||
|
common infrastructure. currently identified services include:
|
||||||
|
|
||||||
|
- cpu load tracking
|
||||||
|
- buffering and conversion service (same code works for input and output)
|
||||||
|
- should support buffer multiplexing (non-integer length input and output buffers)
|
||||||
|
- in-place conversion where possible (only for callback, read/write always copies)
|
||||||
|
- should manage allocation of temporary buffers if necessary
|
||||||
|
- instrumentation (should be able to be disabled): callback count, framesProcessed
|
||||||
|
- common data: magic, streamInterface, callback, userdata
|
||||||
|
|
||||||
|
|
||||||
|
- conversion functions:
|
||||||
|
- should handle temp buffer allocation
|
||||||
|
- dithering (random number state per-stream)
|
||||||
|
- buffer size mismatches
|
||||||
|
- with new buffer slip rules, temp buffers may always be needed
|
||||||
|
- we should aim for in-place conversion wherever possible
|
||||||
|
- does phil's code support in-place conversion? (yes)
|
||||||
|
|
||||||
|
- dicuss relationship between user and host buffer sizes
|
||||||
|
- completely independent.. individual implementations may constrain
|
||||||
|
host buffer sizes if necessary
|
||||||
|
|
||||||
|
|
||||||
|
- discuss device capabilities:
|
||||||
|
- i'd like to be able to request certain information:
|
||||||
|
- channel count for example
|
||||||
|
|
||||||
57
portaudio-v19/aclocal.m4
vendored
Normal file
57
portaudio-v19/aclocal.m4
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
|
||||||
|
dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
|
||||||
|
dnl also defines GSTUFF_PKG_ERRORS on error
|
||||||
|
AC_DEFUN(PKG_CHECK_MODULES, [
|
||||||
|
succeeded=no
|
||||||
|
|
||||||
|
if test -z "$PKG_CONFIG"; then
|
||||||
|
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$PKG_CONFIG" = "no" ; then
|
||||||
|
echo "*** The pkg-config script could not be found. Make sure it is"
|
||||||
|
echo "*** in your path, or set the PKG_CONFIG environment variable"
|
||||||
|
echo "*** to the full path to pkg-config."
|
||||||
|
echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
|
||||||
|
else
|
||||||
|
PKG_CONFIG_MIN_VERSION=0.9.0
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
|
||||||
|
AC_MSG_CHECKING(for $2)
|
||||||
|
|
||||||
|
if $PKG_CONFIG --exists "$2" ; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
succeeded=yes
|
||||||
|
|
||||||
|
AC_MSG_CHECKING($1_CFLAGS)
|
||||||
|
$1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
|
||||||
|
AC_MSG_RESULT($$1_CFLAGS)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING($1_LIBS)
|
||||||
|
$1_LIBS=`$PKG_CONFIG --libs "$2"`
|
||||||
|
AC_MSG_RESULT($$1_LIBS)
|
||||||
|
else
|
||||||
|
$1_CFLAGS=""
|
||||||
|
$1_LIBS=""
|
||||||
|
## If we have a custom action on failure, don't print errors, but
|
||||||
|
## do set a variable so people can do so.
|
||||||
|
$1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||||
|
ifelse([$4], ,echo $$1_PKG_ERRORS,)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST($1_CFLAGS)
|
||||||
|
AC_SUBST($1_LIBS)
|
||||||
|
else
|
||||||
|
echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
|
||||||
|
echo "*** See http://www.freedesktop.org/software/pkgconfig"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $succeeded = yes; then
|
||||||
|
ifelse([$3], , :, [$3])
|
||||||
|
else
|
||||||
|
ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
30
portaudio-v19/config.cache
Normal file
30
portaudio-v19/config.cache
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# This file is a shell script that caches the results of configure
|
||||||
|
# tests run on this system so they can be shared between configure
|
||||||
|
# scripts and configure runs. It is not useful on other systems.
|
||||||
|
# If it contains results you don't want to keep, you may remove or edit it.
|
||||||
|
#
|
||||||
|
# By default, configure uses ./config.cache as the cache file,
|
||||||
|
# creating it if it does not exist already. You can give configure
|
||||||
|
# the --cache-file=FILE option to use a different cache file; that is
|
||||||
|
# what configure does when it calls configure scripts in
|
||||||
|
# subdirectories, so they share the cache.
|
||||||
|
# Giving --cache-file=/dev/null disables caching, for debugging configure.
|
||||||
|
# config.status only pays attention to the cache file if you give it the
|
||||||
|
# --recheck option to rerun configure.
|
||||||
|
#
|
||||||
|
ac_cv_c_bigendian=${ac_cv_c_bigendian=no}
|
||||||
|
ac_cv_lib_asound_snd_pcm_open=${ac_cv_lib_asound_snd_pcm_open=no}
|
||||||
|
ac_cv_lib_pthread_pthread_create=${ac_cv_lib_pthread_pthread_create=yes}
|
||||||
|
ac_cv_path_AR=${ac_cv_path_AR=/usr/bin/ar}
|
||||||
|
ac_cv_path_PKG_CONFIG=${ac_cv_path_PKG_CONFIG=/usr/local/bin/pkg-config}
|
||||||
|
ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'}
|
||||||
|
ac_cv_prog_CC=${ac_cv_prog_CC=cc}
|
||||||
|
ac_cv_prog_RANLIB=${ac_cv_prog_RANLIB=ranlib}
|
||||||
|
ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no}
|
||||||
|
ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes}
|
||||||
|
ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes}
|
||||||
|
ac_cv_prog_gcc=${ac_cv_prog_gcc=yes}
|
||||||
|
ac_cv_sizeof_int=${ac_cv_sizeof_int=4}
|
||||||
|
ac_cv_sizeof_long=${ac_cv_sizeof_long=4}
|
||||||
|
ac_cv_sizeof_short=${ac_cv_sizeof_short=2}
|
||||||
|
lt_cv_sys_max_cmd_len=${lt_cv_sys_max_cmd_len=262144}
|
||||||
185
portaudio-v19/config.doxy
Normal file
185
portaudio-v19/config.doxy
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
# Doxyfile 1.2.13-20020210
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# General configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
PROJECT_NAME = PortAudio
|
||||||
|
PROJECT_NUMBER = 2.0
|
||||||
|
OUTPUT_DIRECTORY = "./docs/"
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
EXTRACT_ALL = YES
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_STATIC = NO
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = NO
|
||||||
|
STRIP_FROM_PATH =
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
CASE_SENSE_NAMES = YES
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
DETAILS_AT_TOP = NO
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
TAB_SIZE = 8
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
ALIASES =
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to warning and progress messages
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
QUIET = NO
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = YES
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the input files
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
INPUT = ./pa_common ./pa_win_wmme ./pa_asio ./pa_win_ds ./pa_linux_alsa ./pa_unix_oss ./pa_jack ./pa_tests
|
||||||
|
FILE_PATTERNS = *.h *.c *.cpp
|
||||||
|
RECURSIVE = YES
|
||||||
|
EXCLUDE =
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
EXAMPLE_PATTERNS =
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to source browsing
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SOURCE_BROWSER = NO
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
REFERENCED_BY_RELATION = YES
|
||||||
|
REFERENCES_RELATION = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the alphabetical class index
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ALPHABETICAL_INDEX = NO
|
||||||
|
COLS_IN_ALPHA_INDEX = 5
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the HTML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = doxygen_html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_ALIGN_MEMBERS = YES
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
GENERATE_TREEVIEW = NO
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the LaTeX output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
COMPACT_LATEX = NO
|
||||||
|
PAPER_TYPE = a4wide
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
PDF_HYPERLINKS = NO
|
||||||
|
USE_PDFLATEX = NO
|
||||||
|
LATEX_BATCHMODE = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the RTF output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = NO
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the man page output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_LINKS = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the XML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_XML = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options for the AutoGen Definitions output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the preprocessor
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH =
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED =
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::addtions related to external references
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE =
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
PERL_PATH = /usr/bin/perl
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the dot tool
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
CLASS_DIAGRAMS = NO
|
||||||
|
HIDE_UNDOC_RELATIONS = NO
|
||||||
|
HAVE_DOT = NO
|
||||||
|
CLASS_GRAPH = YES
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
TEMPLATE_RELATIONS = YES
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DOT_IMAGE_FORMAT = png
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
MAX_DOT_GRAPH_WIDTH = 1024
|
||||||
|
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::addtions related to the search engine
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SEARCHENGINE = NO
|
||||||
|
CGI_NAME = search.cgi
|
||||||
|
CGI_URL =
|
||||||
|
DOC_URL =
|
||||||
|
DOC_ABSPATH =
|
||||||
|
BIN_ABSPATH = /usr/local/bin/
|
||||||
|
EXT_DOC_PATHS =
|
||||||
1407
portaudio-v19/config.guess
vendored
Executable file
1407
portaudio-v19/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
23
portaudio-v19/config.log
Normal file
23
portaudio-v19/config.log
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
This file contains any messages produced by compilers while
|
||||||
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
|
configure:618: checking for gcc
|
||||||
|
configure:731: checking whether the C compiler (cc ) works
|
||||||
|
configure:747: cc -o conftest conftest.c 1>&5
|
||||||
|
configure:773: checking whether the C compiler (cc ) is a cross-compiler
|
||||||
|
configure:778: checking whether we are using GNU C
|
||||||
|
configure:806: checking whether cc accepts -g
|
||||||
|
configure:840: checking for ranlib
|
||||||
|
configure:898: checking for a BSD compatible install
|
||||||
|
configure:953: checking for ar
|
||||||
|
configure:991: checking whether byte ordering is bigendian
|
||||||
|
configure:1083: checking for snd_pcm_open in -lasound
|
||||||
|
configure:1131: checking host system type
|
||||||
|
configure:1159: checking for pkg-config
|
||||||
|
configure:1203: checking for jack
|
||||||
|
configure:1210: checking JACK_CFLAGS
|
||||||
|
configure:1215: checking JACK_LIBS
|
||||||
|
configure:1244: checking size of short
|
||||||
|
configure:1283: checking size of int
|
||||||
|
configure:1322: checking size of long
|
||||||
|
configure:1632: checking for pthread_create in -lpthread
|
||||||
175
portaudio-v19/config.status
Executable file
175
portaudio-v19/config.status
Executable file
@ -0,0 +1,175 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Generated automatically by configure.
|
||||||
|
# Run this file to recreate the current configuration.
|
||||||
|
# This directory was configured as follows,
|
||||||
|
# on host night.db.net:
|
||||||
|
#
|
||||||
|
# ./configure --with-jack=no
|
||||||
|
#
|
||||||
|
# Compiler output produced by configure, useful for debugging
|
||||||
|
# configure, is in ./config.log if it exists.
|
||||||
|
|
||||||
|
ac_cs_usage="Usage: ./config.status [--recheck] [--version] [--help]"
|
||||||
|
for ac_option
|
||||||
|
do
|
||||||
|
case "$ac_option" in
|
||||||
|
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
|
||||||
|
echo "running ${CONFIG_SHELL-/bin/sh} ./configure --with-jack=no --no-create --no-recursion"
|
||||||
|
exec ${CONFIG_SHELL-/bin/sh} ./configure --with-jack=no --no-create --no-recursion ;;
|
||||||
|
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
|
||||||
|
echo "./config.status generated by autoconf version 2.13"
|
||||||
|
exit 0 ;;
|
||||||
|
-help | --help | --hel | --he | --h)
|
||||||
|
echo "$ac_cs_usage"; exit 0 ;;
|
||||||
|
*) echo "$ac_cs_usage"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
ac_given_srcdir=.
|
||||||
|
ac_given_INSTALL="/usr/bin/install -c"
|
||||||
|
|
||||||
|
trap 'rm -fr Makefile conftest*; exit 1' 1 2 15
|
||||||
|
|
||||||
|
# Protect against being on the right side of a sed subst in config.status.
|
||||||
|
sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\&%]/\\&/g;
|
||||||
|
s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
|
||||||
|
/^[ ]*VPATH[ ]*=[^:]*$/d
|
||||||
|
|
||||||
|
s%@SHELL@%/usr/local/bin/bash%g
|
||||||
|
s%@CFLAGS@%-g -O2 -Wall -pedantic -pipe -fPIC -DPA_LITTLE_ENDIAN%g
|
||||||
|
s%@CPPFLAGS@%%g
|
||||||
|
s%@CXXFLAGS@%%g
|
||||||
|
s%@FFLAGS@%%g
|
||||||
|
s%@DEFS@% -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DHAVE_LIBPTHREAD=1 -DPA_USE_OSS=1 %g
|
||||||
|
s%@LDFLAGS@%%g
|
||||||
|
s%@LIBS@%-lpthread -lm -lpthread%g
|
||||||
|
s%@exec_prefix@%${prefix}%g
|
||||||
|
s%@prefix@%/usr/local%g
|
||||||
|
s%@program_transform_name@%s,x,x,%g
|
||||||
|
s%@bindir@%${exec_prefix}/bin%g
|
||||||
|
s%@sbindir@%${exec_prefix}/sbin%g
|
||||||
|
s%@libexecdir@%${exec_prefix}/libexec%g
|
||||||
|
s%@datadir@%${prefix}/share%g
|
||||||
|
s%@sysconfdir@%${prefix}/etc%g
|
||||||
|
s%@sharedstatedir@%${prefix}/com%g
|
||||||
|
s%@localstatedir@%${prefix}/var%g
|
||||||
|
s%@libdir@%${exec_prefix}/lib%g
|
||||||
|
s%@includedir@%${prefix}/include%g
|
||||||
|
s%@oldincludedir@%/usr/include%g
|
||||||
|
s%@infodir@%${prefix}/info%g
|
||||||
|
s%@mandir@%${prefix}/man%g
|
||||||
|
s%@CC@%cc%g
|
||||||
|
s%@RANLIB@%ranlib%g
|
||||||
|
s%@INSTALL_PROGRAM@%${INSTALL}%g
|
||||||
|
s%@INSTALL_SCRIPT@%${INSTALL_PROGRAM}%g
|
||||||
|
s%@INSTALL_DATA@%${INSTALL} -m 644%g
|
||||||
|
s%@AR@%/usr/bin/ar%g
|
||||||
|
s%@host@%i386-unknown-freebsd7.0%g
|
||||||
|
s%@host_alias@%i386-unknown-freebsd7.0%g
|
||||||
|
s%@host_cpu@%i386%g
|
||||||
|
s%@host_vendor@%unknown%g
|
||||||
|
s%@host_os@%freebsd7.0%g
|
||||||
|
s%@PKG_CONFIG@%/usr/local/bin/pkg-config%g
|
||||||
|
s%@JACK_CFLAGS@%-I/usr/local/include %g
|
||||||
|
s%@JACK_LIBS@%-pthread -L/usr/local/lib -ljack %g
|
||||||
|
s%@OTHER_OBJS@% pa_unix_oss/pa_unix_oss.o pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o%g
|
||||||
|
s%@PADLL@%libportaudio.so%g
|
||||||
|
s%@SHARED_FLAGS@%-shared -fPIC%g
|
||||||
|
s%@DLL_LIBS@%%g
|
||||||
|
s%@NASM@%%g
|
||||||
|
s%@NASMOPT@%%g
|
||||||
|
|
||||||
|
CEOF
|
||||||
|
|
||||||
|
# Split the substitutions into bite-sized pieces for seds with
|
||||||
|
# small command number limits, like on Digital OSF/1 and HP-UX.
|
||||||
|
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
|
||||||
|
ac_file=1 # Number of current file.
|
||||||
|
ac_beg=1 # First line for current file.
|
||||||
|
ac_end=$ac_max_sed_cmds # Line after last line for current file.
|
||||||
|
ac_more_lines=:
|
||||||
|
ac_sed_cmds=""
|
||||||
|
while $ac_more_lines; do
|
||||||
|
if test $ac_beg -gt 1; then
|
||||||
|
sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
|
||||||
|
else
|
||||||
|
sed "${ac_end}q" conftest.subs > conftest.s$ac_file
|
||||||
|
fi
|
||||||
|
if test ! -s conftest.s$ac_file; then
|
||||||
|
ac_more_lines=false
|
||||||
|
rm -f conftest.s$ac_file
|
||||||
|
else
|
||||||
|
if test -z "$ac_sed_cmds"; then
|
||||||
|
ac_sed_cmds="sed -f conftest.s$ac_file"
|
||||||
|
else
|
||||||
|
ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
|
||||||
|
fi
|
||||||
|
ac_file=`expr $ac_file + 1`
|
||||||
|
ac_beg=$ac_end
|
||||||
|
ac_end=`expr $ac_end + $ac_max_sed_cmds`
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$ac_sed_cmds"; then
|
||||||
|
ac_sed_cmds=cat
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONFIG_FILES=${CONFIG_FILES-"Makefile"}
|
||||||
|
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
|
||||||
|
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
|
||||||
|
case "$ac_file" in
|
||||||
|
*:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
|
||||||
|
ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
|
||||||
|
*) ac_file_in="${ac_file}.in" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
|
||||||
|
|
||||||
|
# Remove last slash and all that follows it. Not all systems have dirname.
|
||||||
|
ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
|
||||||
|
if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
|
||||||
|
# The file is in a subdirectory.
|
||||||
|
test ! -d "$ac_dir" && mkdir "$ac_dir"
|
||||||
|
ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
|
||||||
|
# A "../" for each directory in $ac_dir_suffix.
|
||||||
|
ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
|
||||||
|
else
|
||||||
|
ac_dir_suffix= ac_dots=
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$ac_given_srcdir" in
|
||||||
|
.) srcdir=.
|
||||||
|
if test -z "$ac_dots"; then top_srcdir=.
|
||||||
|
else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
|
||||||
|
/*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
|
||||||
|
*) # Relative path.
|
||||||
|
srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
|
||||||
|
top_srcdir="$ac_dots$ac_given_srcdir" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$ac_given_INSTALL" in
|
||||||
|
[/$]*) INSTALL="$ac_given_INSTALL" ;;
|
||||||
|
*) INSTALL="$ac_dots$ac_given_INSTALL" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo creating "$ac_file"
|
||||||
|
rm -f "$ac_file"
|
||||||
|
configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
|
||||||
|
case "$ac_file" in
|
||||||
|
*Makefile*) ac_comsub="1i\\
|
||||||
|
# $configure_input" ;;
|
||||||
|
*) ac_comsub= ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
|
||||||
|
sed -e "$ac_comsub
|
||||||
|
s%@configure_input@%$configure_input%g
|
||||||
|
s%@srcdir@%$srcdir%g
|
||||||
|
s%@top_srcdir@%$top_srcdir%g
|
||||||
|
s%@INSTALL@%$INSTALL%g
|
||||||
|
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
|
||||||
|
fi; done
|
||||||
|
rm -f conftest.s*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
exit 0
|
||||||
1504
portaudio-v19/config.sub
vendored
Executable file
1504
portaudio-v19/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1990
portaudio-v19/configure
vendored
Executable file
1990
portaudio-v19/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
250
portaudio-v19/configure.in
Normal file
250
portaudio-v19/configure.in
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
dnl
|
||||||
|
dnl portaudio V19 configure.in script
|
||||||
|
dnl
|
||||||
|
dnl Dominic Mazzoni, Arve Knudsen
|
||||||
|
dnl
|
||||||
|
|
||||||
|
dnl Require autoconf >= 2.13
|
||||||
|
AC_PREREQ(2.13)
|
||||||
|
|
||||||
|
dnl Init autoconf and make sure configure is being called
|
||||||
|
dnl from the right directory
|
||||||
|
AC_INIT([pa_common/portaudio.h])
|
||||||
|
|
||||||
|
dnl Specify options
|
||||||
|
|
||||||
|
AC_ARG_WITH(alsa,
|
||||||
|
[ --with-alsa (default=yes)],
|
||||||
|
with_alsa=$withval, with_alsa="yes")
|
||||||
|
|
||||||
|
AC_ARG_WITH(jack,
|
||||||
|
[ --with-jack (default=yes)],
|
||||||
|
with_jack=$withval, with_jack="yes")
|
||||||
|
|
||||||
|
AC_ARG_WITH(oss,
|
||||||
|
[ --with-oss (default=yes)],
|
||||||
|
with_oss=$withval, with_oss="yes")
|
||||||
|
|
||||||
|
AC_ARG_WITH(host_os,
|
||||||
|
[ --with-host_os (no default)],
|
||||||
|
host_os=$withval)
|
||||||
|
|
||||||
|
AC_ARG_WITH(winapi,
|
||||||
|
[ --with-winapi ((wmme/directx/asio) default=wmme)],
|
||||||
|
with_winapi=$withval, with_winapi="wmme")
|
||||||
|
|
||||||
|
dnl Mac API added for ASIO, can have other api's listed
|
||||||
|
AC_ARG_WITH(macapi,
|
||||||
|
[ --with-macapi ((asio/core/sm) default=core)],
|
||||||
|
with_macapi=$withval, with_macapi="core")
|
||||||
|
|
||||||
|
AC_ARG_WITH(asiodir,
|
||||||
|
[ --with-asiodir (default=/usr/local/asiosdk2)],
|
||||||
|
with_asiodir=$withval, with_asiodir="/usr/local/asiosdk2")
|
||||||
|
|
||||||
|
AC_ARG_WITH(dxdir,
|
||||||
|
[ --with-dxdir (default=/usr/local/dx7sdk)],
|
||||||
|
with_dxdir=$withval, with_dxdir="/usr/local/dx7sdk")
|
||||||
|
|
||||||
|
|
||||||
|
dnl Checks for programs.
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PATH_PROG(AR, ar, no)
|
||||||
|
if [[ $AR = "no" ]] ; then
|
||||||
|
AC_MSG_ERROR("Could not find ar - needed to create a library");
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl This must be one of the first tests we do or it will fail...
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
|
||||||
|
dnl checks for various host APIs and arguments to configure that
|
||||||
|
dnl turn them on or off
|
||||||
|
|
||||||
|
AC_CHECK_LIB(asound, snd_pcm_open, have_alsa=yes, have_alsa=no)
|
||||||
|
|
||||||
|
dnl Determine the host description for the subsequent test.
|
||||||
|
dnl PKG_CHECK_MODULES seems to check and set the host variable also, but
|
||||||
|
dnl that then requires pkg-config availability which is not standard on
|
||||||
|
dnl MinGW systems and can be a pain to install.
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(JACK, jack, have_jack=yes, have_jack=no)
|
||||||
|
|
||||||
|
dnl sizeof checks: we will need a 16-bit and a 32-bit type
|
||||||
|
|
||||||
|
AC_CHECK_SIZEOF(short)
|
||||||
|
AC_CHECK_SIZEOF(int)
|
||||||
|
AC_CHECK_SIZEOF(long)
|
||||||
|
|
||||||
|
dnl extra variables
|
||||||
|
AC_SUBST(OTHER_OBJS)
|
||||||
|
AC_SUBST(PADLL)
|
||||||
|
AC_SUBST(SHARED_FLAGS)
|
||||||
|
AC_SUBST(DLL_LIBS)
|
||||||
|
AC_SUBST(CXXFLAGS)
|
||||||
|
AC_SUBST(NASM)
|
||||||
|
AC_SUBST(NASMOPT)
|
||||||
|
|
||||||
|
CFLAGS="-g -O2 -Wall -pedantic -pipe -fPIC"
|
||||||
|
|
||||||
|
if [[ $ac_cv_c_bigendian = "yes" ]] ; then
|
||||||
|
CFLAGS="$CFLAGS -DPA_BIG_ENDIAN"
|
||||||
|
else
|
||||||
|
CFLAGS="$CFLAGS -DPA_LITTLE_ENDIAN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${host_os}" in
|
||||||
|
darwin* )
|
||||||
|
dnl Mac OS X configuration
|
||||||
|
|
||||||
|
AC_DEFINE(PA_USE_COREAUDIO)
|
||||||
|
OTHER_OBJS="pa_mac/pa_mac_hostapis.o pa_unix/pa_unix_util.o pa_mac_core/pa_mac_core.o";
|
||||||
|
LIBS="-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon";
|
||||||
|
PADLL="libportaudio.dylib";
|
||||||
|
SHARED_FLAGS="-framework CoreAudio -framework AudioToolbox -framework -framework AudioUnit -framework Carbon -dynamiclib";
|
||||||
|
if [[ $with_macapi = "asio" ]] ; then
|
||||||
|
if [[ $with_asiodir ]] ; then
|
||||||
|
ASIODIR="$with_asiodir";
|
||||||
|
else
|
||||||
|
ASIODIR="/usr/local/asiosdk2";
|
||||||
|
fi
|
||||||
|
echo "ASIODIR: $ASIODIR";
|
||||||
|
|
||||||
|
OTHER_OBJS="$CFLAGS pa_asio/iasiothiscallresolver.o $ASIODIR/host/asiodrivers.o $ASIODIR/common/asio.o $ASIODIR/host/mac/asioshlib.o";
|
||||||
|
CFLAGS="$CFLAGS -Ipa_asio -I$ASIDIR/host/mac -I$ASIODIR/common";
|
||||||
|
CXXFLAGS="$CFLAGS";
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
mingw* )
|
||||||
|
dnl MingW configuration
|
||||||
|
|
||||||
|
echo "WINAPI: $with_winapi"
|
||||||
|
if [[ $with_winapi = "directx" ]] ; then
|
||||||
|
if [[ $with_dxdir ]] ; then
|
||||||
|
DXDIR="$with_dxdir";
|
||||||
|
else
|
||||||
|
DXDIR="/usr/local/dx7sdk";
|
||||||
|
fi
|
||||||
|
echo "DXDIR: $DXDIR"
|
||||||
|
OTHER_OBJS="pa_win_ds/pa_win_ds.o pa_win_ds/dsound_wrapper.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o";
|
||||||
|
LIBS="-lwinmm -lm -ldsound -lole32";
|
||||||
|
PADLL="portaudio.dll";
|
||||||
|
SHARED_FLAGS="-shared -mthreads";
|
||||||
|
DLL_LIBS="-lwinmm -lm -L./dx7sdk/lib -ldsound -lole32";
|
||||||
|
#VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\"";
|
||||||
|
#CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO";
|
||||||
|
CFLAGS="$CFLAGS -Ipa_common -I$DXDIR/include -DPA_NO_WMME -DPA_NO_ASIO" -DPA_NO_WDMKS;
|
||||||
|
elif [[ $with_winapi = "asio" ]] ; then
|
||||||
|
if [[ $with_asiodir ]] ; then
|
||||||
|
ASIODIR="$with_asiodir";
|
||||||
|
else
|
||||||
|
ASIODIR="/usr/local/asiosdk2";
|
||||||
|
fi
|
||||||
|
echo "ASIODIR: $ASIODIR"
|
||||||
|
|
||||||
|
OTHER_OBJS="pa_asio/pa_asio.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o pa_asio/iasiothiscallresolver.o $ASIODIR/common/asio.o $ASIODIR/host/asiodrivers.o $ASIODIR/host/pc/asiolist.o";
|
||||||
|
LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid";
|
||||||
|
PADLL="portaudio.dll";
|
||||||
|
SHARED_FLAGS="-shared -mthreads";
|
||||||
|
DLL_LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid";
|
||||||
|
CFLAGS="$CFLAGS -ffast-math -fomit-frame-pointer -Ipa_common -Ipa_asio -I$ASIODIR/host/pc -I$ASIODIR/common -I$ASIODIR/host -DPA_NO_WMME -DPA_NO_DS -DPA_NO_WDMKS -DWINDOWS";
|
||||||
|
CXXFLAGS="$CFLAGS";
|
||||||
|
elif [[ $with_winapi = "wdmks" ]] ; then
|
||||||
|
if [[ $with_dxdir ]] ; then
|
||||||
|
DXDIR="$with_dxdir";
|
||||||
|
else
|
||||||
|
DXDIR="/usr/local/dx7sdk";
|
||||||
|
fi
|
||||||
|
echo "DXDIR: $DXDIR"
|
||||||
|
OTHER_OBJS="pa_win_wdmks/pa_win_wdmks.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o";
|
||||||
|
LIBS="-lwinmm -lm -luuid -lsetupapi -lole32";
|
||||||
|
PADLL="portaudio.dll";
|
||||||
|
SHARED_FLAGS="-shared -mthreads";
|
||||||
|
DLL_LIBS="-lwinmm -lm -L./dx7sdk/lib -luuid -lsetupapi -lole32";
|
||||||
|
#VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\"";
|
||||||
|
#CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO";
|
||||||
|
CFLAGS="$CFLAGS -Ipa_common -I$DXDIR/include -DPA_NO_WMME -DPA_NO_DS -DPA_NO_ASIO";
|
||||||
|
else # WMME default
|
||||||
|
OTHER_OBJS="pa_win_wmme/pa_win_wmme.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o";
|
||||||
|
LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid";
|
||||||
|
PADLL="portaudio.dll";
|
||||||
|
SHARED_FLAGS="-shared -mthreads";
|
||||||
|
DLL_LIBS="-lwinmm";
|
||||||
|
CFLAGS="$CFLAGS -Ipa_common -DPA_NO_DS -DPA_NO_ASIO -DPA_NO_WDMKS";
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
cygwin* )
|
||||||
|
dnl Cygwin configuration
|
||||||
|
|
||||||
|
OTHER_OBJS="pa_win_wmme/pa_win_wmme.o";
|
||||||
|
LIBS="-lwinmm -lm";
|
||||||
|
PADLL="portaudio.dll";
|
||||||
|
SHARED_FLAGS="-shared -mthreads";
|
||||||
|
DLL_LIBS="-lwinmm";
|
||||||
|
;;
|
||||||
|
|
||||||
|
irix* )
|
||||||
|
dnl SGI IRIX audio library (AL) configuration (Pieter, oct 2-13, 2003).
|
||||||
|
dnl The 'dmedia' library is needed to read the Unadjusted System Time (UST).
|
||||||
|
dnl
|
||||||
|
AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR([IRIX posix thread library not found!]))
|
||||||
|
AC_CHECK_LIB(audio, alOpenPort, , AC_MSG_ERROR([IRIX audio library not found!]))
|
||||||
|
AC_CHECK_LIB(dmedia, dmGetUST, , AC_MSG_ERROR([IRIX digital media library not found!]))
|
||||||
|
|
||||||
|
dnl See the '#ifdef PA_USE_SGI' in file pa_unix/pa_unix_hostapis.c
|
||||||
|
dnl which selects the appropriate PaXXX_Initialize() function.
|
||||||
|
dnl
|
||||||
|
AC_DEFINE(PA_USE_SGI)
|
||||||
|
|
||||||
|
dnl The _REENTRANT option for pthread safety. Perhaps not necessary but it 'll do no harm.
|
||||||
|
dnl
|
||||||
|
CFLAGS="$CFLAGS -D_REENTRANT"
|
||||||
|
|
||||||
|
OTHER_OBJS="pa_sgi/pa_sgi.o pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o";
|
||||||
|
|
||||||
|
dnl SGI books say -lpthread should be the last of the libs mentioned.
|
||||||
|
dnl
|
||||||
|
LIBS="-lm -ldmedia -laudio -lpthread";
|
||||||
|
PADLL="libportaudio.so";
|
||||||
|
SHARED_FLAGS="-shared";
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
dnl Unix configuration
|
||||||
|
|
||||||
|
AC_CHECK_LIB(pthread, pthread_create,
|
||||||
|
,
|
||||||
|
AC_MSG_ERROR([libpthread not found!]))
|
||||||
|
|
||||||
|
if [[ $have_alsa = "yes" ] && [ $with_alsa != "no" ]] ; then
|
||||||
|
LIBS="$LIBS -lasound"
|
||||||
|
DLL_LIBS="$DLL_LIBS -lasound"
|
||||||
|
OTHER_OBJS="$OTHER_OBJS pa_linux_alsa/pa_linux_alsa.o"
|
||||||
|
AC_DEFINE(PA_USE_ALSA)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $have_jack = "yes" ] && [ $with_jack != "no" ]] ; then
|
||||||
|
LIBS="$LIBS $JACK_LIBS"
|
||||||
|
DLL_LIBS="$DLL_LIBS $JACK_LIBS"
|
||||||
|
CFLAGS="$CFLAGS $JACK_CFLAGS"
|
||||||
|
OTHER_OBJS="$OTHER_OBJS pa_jack/pa_jack.o"
|
||||||
|
AC_DEFINE(PA_USE_JACK)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $with_oss != "no" ]] ; then
|
||||||
|
OTHER_OBJS="$OTHER_OBJS pa_unix_oss/pa_unix_oss.o"
|
||||||
|
AC_DEFINE(PA_USE_OSS)
|
||||||
|
fi
|
||||||
|
LIBS="$LIBS -lm -lpthread";
|
||||||
|
PADLL="libportaudio.so";
|
||||||
|
SHARED_FLAGS="-shared -fPIC";
|
||||||
|
|
||||||
|
OTHER_OBJS="$OTHER_OBJS pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o"
|
||||||
|
esac
|
||||||
|
|
||||||
|
AC_OUTPUT([Makefile])
|
||||||
60
portaudio-v19/docs/index.html
Normal file
60
portaudio-v19/docs/index.html
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="PortAudio Docs, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Docs</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Documentation</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<p>Copyright 2000 Phil Burk and Ross Bencina
|
||||||
|
<br>
|
||||||
|
<h3>
|
||||||
|
<a href="portaudio_h.txt">API Reference</a></h3>
|
||||||
|
|
||||||
|
<blockquote>The Application Programmer Interface is documented in "portaudio.h".</blockquote>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="pa_tutorial.html">Tutorial</a></h3>
|
||||||
|
|
||||||
|
<blockquote>Describes how to write audio programs using the PortAudio API.</blockquote>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="pa_impl_guide.html">Implementation Guide</a></h3>
|
||||||
|
|
||||||
|
<blockquote>Describes how to write an implementation of PortAudio for a
|
||||||
|
new computer platform.</blockquote>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="portaudio_icmc2001.pdf">Paper Presented at ICMC2001</a> (PDF)</h3>
|
||||||
|
|
||||||
|
<blockquote>Describes the PortAudio API and discusses implementation issues.
|
||||||
|
Written July 2001.</blockquote>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="latency.html">Improving Latency</a></h3>
|
||||||
|
|
||||||
|
<blockquote>How to tune your computer to achieve the lowest possible audio
|
||||||
|
delay.</blockquote>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="proposals.html">Proposed Changes</a></h3>
|
||||||
|
|
||||||
|
<blockquote>Describes API changes being considered by the developer community.
|
||||||
|
Feedback welcome.</blockquote>
|
||||||
|
<a href="http://www.portaudio.com/">Return to PortAudio Home Page</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
192
portaudio-v19/docs/latency.html
Normal file
192
portaudio-v19/docs/latency.html
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Internal docs. How a stream is started or stopped.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Implementation - Start/Stop</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
<a href="http://www.portaudio.com">PortAudio</a> Latency</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<p>This page discusses the issues of audio latency for <a href="http://www.portaudio.com">PortAudio</a>
|
||||||
|
. It offers suggestions on how to lower latency to improve the responsiveness
|
||||||
|
of applications.
|
||||||
|
<blockquote><b><a href="#what">What is Latency?</a></b>
|
||||||
|
<br><b><a href="#portaudio">PortAudio and Latency</a></b>
|
||||||
|
<br><b><a href="#macintosh">Macintosh</a></b>
|
||||||
|
<br><b><a href="#unix">Unix</a></b>
|
||||||
|
<br><b><a href="#windows">WIndows</a></b></blockquote>
|
||||||
|
By Phil Burk, Copyright 2002 Phil Burk and Ross Bencina
|
||||||
|
<h2>
|
||||||
|
<a NAME="what"></a>What is Latency?</h2>
|
||||||
|
Latency is basically longest time that you have to wait before you obtain
|
||||||
|
a desired result. For digital audio output it is the time between making
|
||||||
|
a sound in software and finally hearing it.
|
||||||
|
<p>Consider the example of pressing a key on the ASCII keyboard to play
|
||||||
|
a note. There are several stages in this process which each contribute
|
||||||
|
their own latency. First the operating system must respond to the keypress.
|
||||||
|
Then the audio signal generated must work its way through the PortAudio
|
||||||
|
buffers. Then it must work its way through the audio card hardware. Then
|
||||||
|
it must go through the audio amplifier which is very quick and then travel
|
||||||
|
through the air. Sound travels at abous one foot per millisecond through
|
||||||
|
air so placing speakers across the room can add 5-20 msec of delay.
|
||||||
|
<p>The reverse process occurs when recording or responding to audio input.
|
||||||
|
If you are processing audio, for example if you implement a software guitar
|
||||||
|
fuzz box, then you have both the audio input and audio output latencies
|
||||||
|
added together.
|
||||||
|
<p>The audio buffers are used to prevent glitches in the audio stream.
|
||||||
|
The user software writes audio into the output buffers. That audio is read
|
||||||
|
by the low level audio driver or by DMA and sent to the DAC. If the computer
|
||||||
|
gets busy doing something like reading the disk or redrawing the screen,
|
||||||
|
then it may not have time to fill the audio buffer. The audio hardware
|
||||||
|
then runs out of audio data, which causes a glitch. By using a large enough
|
||||||
|
buffer we can ensure that there is always enough audio data for the audio
|
||||||
|
hardware to play. But if the buffer is too large then the latency is high
|
||||||
|
and the system feels sluggish. If you play notes on the keyboard then the
|
||||||
|
"instrument" will feel unresponsive. So you want the buffers to be as small
|
||||||
|
as possible without glitching.
|
||||||
|
<h2>
|
||||||
|
<a NAME="portaudio"></a>PortAudio and Latency</h2>
|
||||||
|
The only delay that PortAudio can control is the total length of its buffers.
|
||||||
|
The Pa_OpenStream() call takes two parameters: numBuffers and framesPerBuffer.
|
||||||
|
The latency is also affected by the sample rate which we will call framesPerSecond.
|
||||||
|
A frame is a set of samples that occur simultaneously. For a stereo stream,
|
||||||
|
a frame is two samples.
|
||||||
|
<p>The latency in milliseconds due to this buffering is:
|
||||||
|
<blockquote><tt>latency_msec = 1000 * numBuffers * framesPerBuffer / framesPerSecond</tt></blockquote>
|
||||||
|
This is not the total latency, as we have seen, but it is the part we can
|
||||||
|
control.
|
||||||
|
<p>If you call Pa_OpenStream() with numBuffers equal to zero, then PortAudio
|
||||||
|
will select a conservative number that will prevent audio glitches. If
|
||||||
|
you still get glitches, then you can pass a larger value for numBuffers
|
||||||
|
until the glitching stops. if you try to pass a numBuffers value that is
|
||||||
|
too small, then PortAudio will use its own idea of the minimum value.
|
||||||
|
<p>PortAudio decides on the minimum number of buffers in a conservative
|
||||||
|
way based on the frameRate, operating system and other variables. You can
|
||||||
|
query the value that PortAudio will use by calling:
|
||||||
|
<blockquote><tt>int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate
|
||||||
|
);</tt></blockquote>
|
||||||
|
On some systems you can override the PortAudio minimum if you know your
|
||||||
|
system can handle a lower value. You do this by setting an environment
|
||||||
|
variable called PA_MIN_LATENCY_MSEC which is read by PortAudio when it
|
||||||
|
starts up. This is supported on the PortAudio implementations for Windows
|
||||||
|
MME, Windows DirectSound, and Unix OSS.
|
||||||
|
<h2>
|
||||||
|
<a NAME="macintosh"></a>Macintosh</h2>
|
||||||
|
The best thing you can do to improve latency on Mac OS 8 and 9 is to turn
|
||||||
|
off Virtual Memory. PortAudio V18 will detect that Virtual Memory is turned
|
||||||
|
off and use a very low latency.
|
||||||
|
<p>For Mac OS X the latency is very low because Apple Core Audio is so
|
||||||
|
well written. You can set the PA_MIN_LATENCY_MSEC variable using:
|
||||||
|
<blockquote><tt>setenv PA_MIN_LATENCY_MSEC 4</tt></blockquote>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a NAME="unix"></a>Unix</h2>
|
||||||
|
PortAudio under Unix currently uses a backgroud thread that reads and writes
|
||||||
|
to OSS. This gives you decent but not great latency. But if you raise the
|
||||||
|
priority of the background thread to a very priority then you can get under
|
||||||
|
10 milliseconds latency. In order to raise your priority you must run the
|
||||||
|
PortAudio program as root! You must also set PA_MIN_LATENCY_MSEC using
|
||||||
|
the appropriate command for your shell.
|
||||||
|
<h2>
|
||||||
|
<a NAME="windows"></a>Windows</h2>
|
||||||
|
Latency under Windows is a complex issue because of all the alternative
|
||||||
|
operating system versions and device drivers. I have seen latency range
|
||||||
|
from 8 milliseconds to 400 milliseconds. The worst case is when using Windows
|
||||||
|
NT. Windows 98 is a little better, and Windows XP can be quite good if
|
||||||
|
properly tuned.
|
||||||
|
<p>The underlying audio API also makes a lot of difference. If the audio
|
||||||
|
device has its own DirectSound driver then DirectSound can often provide
|
||||||
|
better latency than WMME. But if a real DirectSound driver is not available
|
||||||
|
for your device then it is emulated using WMME and the latency can be very
|
||||||
|
high. That's where I saw the 400 millisecond latency. The ASIO implementation
|
||||||
|
is generally very good and will give the lowest latency if available.
|
||||||
|
<p>You can set the PA_MIN_LATENCY_MSEC variable to 50, for example, by
|
||||||
|
entering in MS-DOS:
|
||||||
|
<blockquote><tt>set PA_MIN_LATENCY_MSEC=50</tt></blockquote>
|
||||||
|
If you enter this in a DOS window then you must run the PortAudio program
|
||||||
|
from that same window for the variable to have an effect. You can add that
|
||||||
|
line to your C:\AUTOEXEC.BAT file and reboot if you want it to affect any
|
||||||
|
PortAudio based program.
|
||||||
|
<p>For Windows XP, you can set environment variables as follows:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Select "Control Panel" from the "Start Menu".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Launch the "System" Control Panel</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click on the "Advanced" tab.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click on the "Environment Variables" button.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click "New" button under User Variables.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Enter PA_MIN_LATENCY_MSEC for the name and some optimistic number for the
|
||||||
|
value.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click OK, OK, OK.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Improving Latency on Windows</h3>
|
||||||
|
There are several steps you can take to improve latency under windows.
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Avoid reading or writng to disk when doing audio.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Turn off all automated background tasks such as email clients, virus scanners,
|
||||||
|
backup programs, FTP servers, web servers, etc. when doing audio.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Disconnect from the network to prevent network traffic from interrupting
|
||||||
|
your CPU.</li>
|
||||||
|
</ol>
|
||||||
|
<b>Important: </b>Windows XP users can also tune the OS to favor background
|
||||||
|
tasks, such as audio, over foreground tasks, such as word processing. I
|
||||||
|
lowered my latency from 40 to 10 milliseconds using this simple technique.
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Select "Control Panel" from the "Start Menu".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Launch the "System" Control Panel</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click on the "Advanced" tab.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click on the "Settings" button in the Performance area.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click on the "Advanced" tab.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Select "Background services" in the Processor Scheduling area.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Click OK, OK.</li>
|
||||||
|
</ol>
|
||||||
|
Please let us know if you have others sugestions for lowering latency.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
197
portaudio-v19/docs/pa_impl_guide.html
Normal file
197
portaudio-v19/docs/pa_impl_guide.html
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Internal docs. How a stream is started or stopped.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Implementation - Start/Stop</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
<a href="http://www.portaudio.com">PortAudio</a> Implementation Guide</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<p>This document describes how to implement the PortAudio API on a new
|
||||||
|
computer platform. Implementing PortAudio on a new platform, makes it possible
|
||||||
|
to port many existing audio applications to that platform.
|
||||||
|
<p>By Phil Burk
|
||||||
|
<br>Copyright 2000 Phil Burk and Ross Bencina
|
||||||
|
<p>Note that the license says: <b>"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."</b>.
|
||||||
|
So when you have finished a new implementation, please send it back to
|
||||||
|
us at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>"
|
||||||
|
so that we can make it available for other users. Thank you!
|
||||||
|
<h2>
|
||||||
|
Download the Latest PortAudio Implementation</h2>
|
||||||
|
Always start with the latest implementation available at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>".
|
||||||
|
Look for the nightly snapshot under the CVS section.
|
||||||
|
<h2>
|
||||||
|
Select an Existing Implementation as a Basis</h2>
|
||||||
|
The fastest way to get started is to take an existing implementation and
|
||||||
|
translate it for your new platform. Choose an implementation whose architecture
|
||||||
|
is as close as possible to your target.
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
DirectSound Implementation - pa_win_ds - Uses a timer callback for the
|
||||||
|
background "thread". Polls a circular buffer and writes blocks of data
|
||||||
|
to keep it full.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Windows MME - pa_win_wmme - Spawns an actual Win32 thread. Writes blocks
|
||||||
|
of data to the HW device and waits for events that signal buffer completion.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Linux OSS - pa_linux - Spawns a real thread that writes to the "/dev/dsp"
|
||||||
|
stream using blocking I/O calls.</li>
|
||||||
|
</ul>
|
||||||
|
When you write a new implementation, you will be using some code that is
|
||||||
|
in common with all implementations. This code is in the folder "pa_common".
|
||||||
|
It provides various functions such as parameter checking, error code to
|
||||||
|
text conversion, sample format conversion, clipping and dithering, etc.
|
||||||
|
<p>The code that you write will go into a separate folder called "pa_{os}_{api}".
|
||||||
|
For example, code specific to the DirectSound interface for Windows goes
|
||||||
|
in "pa_win_ds".
|
||||||
|
<h2>
|
||||||
|
Read Docs and Code</h2>
|
||||||
|
Famialiarize yourself with the system by reading the documentation provided.
|
||||||
|
here is a suggested order:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
User Programming <a href="pa_tutorial.html">Tutorial</a></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Header file "pa_common/portaudio.h" which defines API.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Header file "pa_common/pa_host.h" for host dependant code. This definces
|
||||||
|
the routine you will need to provide.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Shared code in "pa_common/pa_lib.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Docs on Implementation of <a href="pa_impl_startstop.html">Start/Stop</a>
|
||||||
|
code.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Implement Output to Default Device</h2>
|
||||||
|
Now we are ready to crank some code. For instant gratification, let's try
|
||||||
|
to play a sine wave.
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Link the test program "pa_tests/patest_sine.c" with the file "pa_lib.c"
|
||||||
|
and the implementation specific file you are creating.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
For now, just stub out the device query code and the audio input code.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Modify PaHost_OpenStream() to open your default target device and get everything
|
||||||
|
setup.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Modify PaHost_StartOutput() to start playing audio.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Modify PaHost_StopOutput() to stop audio.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Modify PaHost_CloseStream() to clean up. Free all memory that you allocated
|
||||||
|
in PaHost_OpenStream().</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Keep cranking until you can play a sine wave using "patest_sine.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Once that works, try "patest_pink.c", "patest_clip.c", "patest_sine8.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
To test your Open and Close code, try "patest_many.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Now test to make sure that the three modes of stopping are properly supported
|
||||||
|
by running "patest_stop.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Test your implementation of time stamping with "patest_sync.c".</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Implement Device Queries</h2>
|
||||||
|
Now that output is working, lets implement the code for querying what devices
|
||||||
|
are available to the user. Run "pa_tests/pa_devs.c". It should print all
|
||||||
|
of the devices available and their characteristics.
|
||||||
|
<h2>
|
||||||
|
Implement Input</h2>
|
||||||
|
Implement audio input and test it with:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
patest_record.c - record in half duplex, play back as recorded.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
patest_wire.c - full duplex, copies input to output. Note that some HW
|
||||||
|
may not support full duplex.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
patest_fuzz.c - plug in your guitar and get a feel for why latency is an
|
||||||
|
important issue in computer music.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
paqa_devs.c - try to open every device and use it with every possible format</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Debugging Tools</h2>
|
||||||
|
You generally cannot use printf() calls to debug real-time processes because
|
||||||
|
they disturb the timing. Also calling printf() from your background thread
|
||||||
|
or interrupt could crash the machine. So PA includes a tool for capturing
|
||||||
|
events and storing the information while it is running. It then prints
|
||||||
|
the events when Pa_Terminate() is called.
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
To enable trace mode, change TRACE_REALTIME_EVENTS in "pa_common/pa_trace.h"
|
||||||
|
from a (0) to a (1).</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Link with "pa_common/pa_trace.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Add trace messages to your code by calling:</li>
|
||||||
|
|
||||||
|
<br><tt> void AddTraceMessage( char *msg, int data );</tt>
|
||||||
|
<br><tt>for example</tt>
|
||||||
|
<br><tt> AddTraceMessage("Pa_TimeSlice: past_NumCallbacks ",
|
||||||
|
past->past_NumCallbacks );</tt>
|
||||||
|
<li>
|
||||||
|
Run your program. You will get a dump of events at the end.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
You can leave the trace messages in your code. They will turn to NOOPs
|
||||||
|
when you change TRACE_REALTIME_EVENTS back to (0).</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Delivery</h2>
|
||||||
|
Please send your new code along with notes on the implementation back to
|
||||||
|
us at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>".
|
||||||
|
We will review the implementation and post it with your name. If you had
|
||||||
|
to make any modifications to the code in "pa_common" or "pa_tests" <b>please</b>
|
||||||
|
send us those modifications and your notes. We will try to merge your changes
|
||||||
|
so that the "pa_common" code works with <b>all</b> implementations.
|
||||||
|
<p>If you have suggestions for how to make future implementations easier,
|
||||||
|
please let us know.
|
||||||
|
<br>THANKS!
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
190
portaudio-v19/docs/pa_impl_startstop.html
Normal file
190
portaudio-v19/docs/pa_impl_startstop.html
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.75 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Internal docs. How a stream is started or stopped.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Implementation - Start/Stop</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Implementation</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Starting and Stopping Streams</h2>
|
||||||
|
PortAudio is generally executed in two "threads". The foreground thread
|
||||||
|
is the application thread. The background "thread" may be implemented as
|
||||||
|
an actual thread, an interrupt handler, or a callback from a timer thread.
|
||||||
|
<p>There are three ways that PortAudio can stop a stream. In each case
|
||||||
|
we look at the sequence of events and the messages sent between the two
|
||||||
|
threads. The following variables are contained in the internalPortAudioStream.
|
||||||
|
<blockquote><tt>int past_IsActive;
|
||||||
|
/* Background is still playing. */</tt>
|
||||||
|
<br><tt>int past_StopSoon; /* Stop
|
||||||
|
when last buffer done. */</tt>
|
||||||
|
<br><tt>int past_StopNow; /*
|
||||||
|
Stop IMMEDIATELY. */</tt></blockquote>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Pa_AbortStream()</h3>
|
||||||
|
This function causes the background thread to terminate as soon as possible
|
||||||
|
and audio I/O to stop abruptly.
|
||||||
|
<br>
|
||||||
|
<table BORDER COLS=2 WIDTH="60%" >
|
||||||
|
<tr>
|
||||||
|
<td><b>Foreground Thread</b></td>
|
||||||
|
|
||||||
|
<td><b>Background Thread</b></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>sets <tt>StopNow</tt></td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>sees <tt>StopNow</tt>, </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>clears IsActive, stops thread</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>waits for thread to exit</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>turns off audio I/O</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Pa_StopStream()</h3>
|
||||||
|
This function stops the user callback function from being called and then
|
||||||
|
waits for all audio data written to the output buffer to be played. In
|
||||||
|
a system with very low latency, you may not hear any difference between
|
||||||
|
<br>
|
||||||
|
<table BORDER COLS=2 WIDTH="60%" >
|
||||||
|
<tr>
|
||||||
|
<td><b>Foreground Thread</b></td>
|
||||||
|
|
||||||
|
<td><b>Background Thread</b></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>sets StopSoon</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>stops calling user callback</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>continues until output buffer empty</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>clears IsActive, stops thread</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>waits for thread to exit</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>turns off audio I/O</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
User callback returns one.</h3>
|
||||||
|
If the user callback returns one then the user callback function will no
|
||||||
|
longer be called. Audio output will continue until all audio data written
|
||||||
|
to the output buffer has been played. Then the audio I/O is stopped, the
|
||||||
|
background thread terminates, and the stream becomes inactive.
|
||||||
|
<br>
|
||||||
|
<table BORDER COLS=2 WIDTH="60%" >
|
||||||
|
<tr>
|
||||||
|
<td><b>Foreground Thread</b></td>
|
||||||
|
|
||||||
|
<td><b>Background Thread</b></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>callback returns 1</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>sets StopSoon</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>stops calling user callback</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>continues until output buffer empty</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>clears IsActive, stops thread</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>waits for thread to exit</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>turns off audio I/O</td>
|
||||||
|
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
55
portaudio-v19/docs/pa_tut_asio.html
Normal file
55
portaudio-v19/docs/pa_tut_asio.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Compiling for ASIO (Windows or Macintosh)</h2>
|
||||||
|
|
||||||
|
<blockquote>ASIO is a low latency audio API from Steinberg. To compile
|
||||||
|
an ASIO application, you must first <a href="http://www.steinberg.net/developers/ASIO2SDKAbout.phtml">download
|
||||||
|
the ASIO SDK</a> from Steinberg. You also need to obtain ASIO drivers for
|
||||||
|
your audio device.
|
||||||
|
<p>Note: I am using '/' as a file separator below. On Macintosh replace
|
||||||
|
'/' with ':'. On Windows, replace '/' with '\'.
|
||||||
|
<p> To use ASIO with the PortAudio library add the following source
|
||||||
|
files to your project:
|
||||||
|
<blockquote>
|
||||||
|
<pre>pa_asio/pa_asio.cpp</pre>
|
||||||
|
</blockquote>
|
||||||
|
and also these files from the ASIO SDK:
|
||||||
|
<blockquote>
|
||||||
|
<pre>common/asio.cpp
|
||||||
|
host/asiodrivers.cpp
|
||||||
|
host/asiolist.cpp</pre>
|
||||||
|
</blockquote>
|
||||||
|
and add these directories to the path for include files
|
||||||
|
<blockquote>
|
||||||
|
<pre>asiosdk2/host/pc (for Windows)
|
||||||
|
asiosdk2/common
|
||||||
|
asiosdk2/host</pre>
|
||||||
|
</blockquote>
|
||||||
|
You may try compiling the "pa_tests/patest_saw.c" file first because it
|
||||||
|
is the simplest.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
91
portaudio-v19/docs/pa_tut_callback.html
Normal file
91
portaudio-v19/docs/pa_tut_callback.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Writing a Callback Function</h2>
|
||||||
|
|
||||||
|
<blockquote>To write a program using PortAudio, you must include the "portaudio.h"
|
||||||
|
include file. You may wish to read "<a href="portaudio_h.txt">portaudio.h</a>"
|
||||||
|
because it contains a complete description of the PortAudio functions and
|
||||||
|
constants.
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include "portaudio.h"</pre>
|
||||||
|
</blockquote>
|
||||||
|
The next task is to write your custom callback function. It is a function
|
||||||
|
that is called by the PortAudio engine whenever it has captured audio data,
|
||||||
|
or when it needs more audio data for output.
|
||||||
|
<p>Your callback function is often called by an interrupt, or low level
|
||||||
|
process so you should not do any complex system activities like allocating
|
||||||
|
memory, or reading or writing files, or printf(). Just crunch numbers and
|
||||||
|
generate audio signals. What is safe or not safe will vary from platform
|
||||||
|
to platform. On the Macintosh, for example, you can only call "interrupt
|
||||||
|
safe" routines. Also do not call any PortAudio functions in the callback
|
||||||
|
except for Pa_StreamTime() and Pa_GetCPULoad().
|
||||||
|
<p>Your callback function must return an int and accept the exact parameters
|
||||||
|
specified in this typedef:
|
||||||
|
<blockquote>
|
||||||
|
<pre>typedef int (PortAudioCallback)(
|
||||||
|
void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaTimestamp outTime, void *userData );</pre>
|
||||||
|
</blockquote>
|
||||||
|
Here is an example callback function from the test file "patests/patest_saw.c".
|
||||||
|
It calculates a simple left and right sawtooth signal and writes it to
|
||||||
|
the output buffer. Notice that in this example, the signals are of <tt>float</tt>
|
||||||
|
data type. The signals must be between -1.0 and +1.0. You can also use
|
||||||
|
16 bit integers or other formats which are specified during setup. You
|
||||||
|
can pass a pointer to your data structure through PortAudio which will
|
||||||
|
appear as <tt>userData</tt>.
|
||||||
|
<blockquote>
|
||||||
|
<pre>int patestCallback( void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaTimestamp outTime, void *userData )
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
/* Cast data passed through stream to our structure type. */
|
||||||
|
paTestData *data = (paTestData*)userData;
|
||||||
|
float *out = (float*)outputBuffer;
|
||||||
|
|
||||||
|
for( i=0; i<framesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
/* Stereo channels are interleaved. */
|
||||||
|
*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;
|
||||||
|
}</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_init.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
65
portaudio-v19/docs/pa_tut_devs.html
Normal file
65
portaudio-v19/docs/pa_tut_devs.html
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.75 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Querying for Available Devices</h2>
|
||||||
|
|
||||||
|
<blockquote>There are often several different audio devices available in
|
||||||
|
a computer with different capabilities. They can differ in the sample rates
|
||||||
|
supported, bit widths, etc. PortAudio provides a simple way to query for
|
||||||
|
the available devices, and then pass the selected device to Pa_OpenStream().
|
||||||
|
For an example, see the file "pa_tests/pa_devs.c".
|
||||||
|
<p>To determine the number of devices:
|
||||||
|
<blockquote>
|
||||||
|
<pre>numDevices = Pa_CountDevices();</pre>
|
||||||
|
</blockquote>
|
||||||
|
You can then query each device in turn by calling Pa_GetDeviceInfo() with
|
||||||
|
an index.
|
||||||
|
<blockquote>
|
||||||
|
<pre>for( i=0; i<numDevices; i++ ) {
|
||||||
|
pdi = Pa_GetDeviceInfo( i );</pre>
|
||||||
|
</blockquote>
|
||||||
|
It will return a pointer to a <tt>PaDeviceInfo</tt> structure which is
|
||||||
|
defined as:
|
||||||
|
<blockquote>
|
||||||
|
<pre>typedef struct{
|
||||||
|
int structVersion;
|
||||||
|
const char *name;
|
||||||
|
int maxInputChannels;
|
||||||
|
int maxOutputChannels;
|
||||||
|
/* Number of discrete rates, or -1 if range supported. */
|
||||||
|
int numSampleRates;
|
||||||
|
/* Array of supported sample rates, or {min,max} if range supported. */
|
||||||
|
const double *sampleRates;
|
||||||
|
PaSampleFormat nativeSampleFormat;
|
||||||
|
}PaDeviceInfo;</pre>
|
||||||
|
</blockquote>
|
||||||
|
If the device supports a continuous range of sample rates, then numSampleRates
|
||||||
|
will equal -1, and the sampleRates array will have two values, the minimum
|
||||||
|
and maximum rate.
|
||||||
|
<p>The device information is allocated by Pa_Initialize() and freed by
|
||||||
|
Pa_Terminate() so you do not have to free() the structure returned by Pa_GetDeviceInfo().</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_util.html">previous</a> | <a href="pa_tut_rw.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
42
portaudio-v19/docs/pa_tut_explore.html
Normal file
42
portaudio-v19/docs/pa_tut_explore.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Exploring PortAudio</h2>
|
||||||
|
|
||||||
|
<blockquote>Now that you have a good idea of how PortAudio works, you can
|
||||||
|
try out the test programs.
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
For an example of playing a sine wave, see "pa_tests/patest_sine.c".</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
For an example of recording and playing back a sound, see "pa_tests/patest_record.c".</li>
|
||||||
|
</ul>
|
||||||
|
I also encourage you to examine the source for the PortAudio libraries.
|
||||||
|
If you have suggestions on ways to improve them, please let us know. if
|
||||||
|
you want to implement PortAudio on a new platform, please let us know as
|
||||||
|
well so we can coordinate people's efforts.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_rw.html">previous</a> | next</font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
43
portaudio-v19/docs/pa_tut_init.html
Normal file
43
portaudio-v19/docs/pa_tut_init.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Initializing PortAudio</h2>
|
||||||
|
|
||||||
|
<blockquote>Before making any other calls to PortAudio, you must call <tt>Pa_Initialize</tt>().
|
||||||
|
This will trigger a scan of available devices which can be queried later.
|
||||||
|
Like most PA functions, it will return a result of type <tt>paError</tt>.
|
||||||
|
If the result is not <tt>paNoError</tt>, then an error has occurred.
|
||||||
|
<blockquote>
|
||||||
|
<pre>err = Pa_Initialize();
|
||||||
|
if( err != paNoError ) goto error;</pre>
|
||||||
|
</blockquote>
|
||||||
|
You can get a text message that explains the error message by passing it
|
||||||
|
to
|
||||||
|
<blockquote>
|
||||||
|
<pre>printf( "PortAudio error: %s\n", Pa_GetErrorText( err ) );</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_callback.html">previous</a> | <a href="pa_tut_open.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
41
portaudio-v19/docs/pa_tut_mac.html
Normal file
41
portaudio-v19/docs/pa_tut_mac.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Compiling for Macintosh</h2>
|
||||||
|
|
||||||
|
<blockquote>To compile a Macintosh application with the PortAudio library,
|
||||||
|
add the following source files to your project:
|
||||||
|
<blockquote>
|
||||||
|
<pre>pa_mac:pa_mac.c
|
||||||
|
pa_common:pa_lib.c
|
||||||
|
pa_common:portaudio.h
|
||||||
|
pa_common:pa_host.h</pre>
|
||||||
|
</blockquote>
|
||||||
|
Also add the Apple <b>SoundLib</b> to your project.
|
||||||
|
<p>You may try compiling the "pa_tests:patest_saw.c" file first because
|
||||||
|
it is the simplest.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
46
portaudio-v19/docs/pa_tut_mac_osx.html
Normal file
46
portaudio-v19/docs/pa_tut_mac_osx.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Compiling for Macintosh OS X</h2>
|
||||||
|
|
||||||
|
<blockquote>To compile a Macintosh OS X CoreAudio application with the
|
||||||
|
PortAudio library:
|
||||||
|
<p>Create a new ProjectBuilder project. You can use a "Tool" project to
|
||||||
|
run the PortAudio examples.
|
||||||
|
<p>Add the following source files to your Project:
|
||||||
|
<blockquote>
|
||||||
|
<pre>pa_mac_core/pa_mac_core.c
|
||||||
|
pa_common/pa_lib.c
|
||||||
|
pa_common/portaudio.h
|
||||||
|
pa_common/pa_host.h
|
||||||
|
pa_common/pa_convert.c</pre>
|
||||||
|
</blockquote>
|
||||||
|
Add the Apple CoreAudio.framework to your project by selecting "Add FrameWorks..."
|
||||||
|
from the Project menu.
|
||||||
|
<p>Compile and run the "pa_tests:patest_saw.c" file first because it is
|
||||||
|
the simplest.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
52
portaudio-v19/docs/pa_tut_open.html
Normal file
52
portaudio-v19/docs/pa_tut_open.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Opening a Stream using Defaults</h2>
|
||||||
|
|
||||||
|
<blockquote>The next step is to open a stream which is similar to opening
|
||||||
|
a file. You can specify whether you want audio input and/or output, how
|
||||||
|
many channels, the data format, sample rate, etc. There are two calls for
|
||||||
|
opening streams, <tt>Pa_OpenStream</tt>() and <tt>Pa_OpenDefaultStream</tt>().
|
||||||
|
<p><tt>Pa_OpenStream()</tt> takes extra parameters which give you
|
||||||
|
more control. You can normally just use <tt>Pa_OpenDefaultStream</tt>()
|
||||||
|
which just calls <tt>Pa_OpenStream()</tt> <tt>with</tt> some reasonable
|
||||||
|
default values. Let's open a stream for stereo output, using floating
|
||||||
|
point data, at 44100 Hz.
|
||||||
|
<blockquote>
|
||||||
|
<pre>err = Pa_OpenDefaultStream(
|
||||||
|
&stream, /* passes back stream pointer */
|
||||||
|
0, /* no input channels */
|
||||||
|
2, /* stereo output */
|
||||||
|
paFloat32, /* 32 bit floating point output */
|
||||||
|
44100, /* sample rate */
|
||||||
|
256, /* frames per buffer */
|
||||||
|
0, /* number of buffers, if zero then use default minimum */
|
||||||
|
patestCallback, /* specify our custom callback */
|
||||||
|
&data ); /* pass our data through to callback */</pre>
|
||||||
|
</blockquote>
|
||||||
|
If you want to use 16 bit integer data, pass <tt>paInt16</tt> instead of
|
||||||
|
<tt>paFloat32</tt>.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_init.html">previous</a> | <a href="pa_tut_run.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
46
portaudio-v19/docs/pa_tut_oss.html
Normal file
46
portaudio-v19/docs/pa_tut_oss.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Compiling for Unix OSS</h2>
|
||||||
|
|
||||||
|
<blockquote>[Skip this page if you are not using Unix and OSS]
|
||||||
|
<p>We currently support the <a href="http://www.opensound.com/">OSS</a>
|
||||||
|
audio drivers for Linux, Solaris, and FreeBSD. We hope to someday support
|
||||||
|
the newer ALSA drivers.
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
cd to pa_unix_oss directory</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Edit the Makefile and uncomment one of the tests. You may try compiling
|
||||||
|
the "patest_sine.c" file first because it is very simple.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
gmake run</li>
|
||||||
|
</ol>
|
||||||
|
</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_pc.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
92
portaudio-v19/docs/pa_tut_over.html
Normal file
92
portaudio-v19/docs/pa_tut_over.html
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Overview of PortAudio</h2>
|
||||||
|
|
||||||
|
<blockquote>PortAudio is a library that provides streaming audio input
|
||||||
|
and output. It is a cross-platform API (Application Programming Interface)
|
||||||
|
that works on Windows, Macintosh, Unix running OSS, SGI, BeOS, and perhaps
|
||||||
|
other platforms by the time you read this. This means that you can write
|
||||||
|
a simple 'C' program to process or generate an audio signal, and that program
|
||||||
|
can run on several different types of computer just by recompiling the
|
||||||
|
source code.
|
||||||
|
<p>Here are the steps to writing a PortAudio application:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Write a callback function that will be called by PortAudio when audio processing
|
||||||
|
is needed.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Initialize the PA library and open a stream for audio I/O.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Start the stream. Your callback function will be now be called repeatedly
|
||||||
|
by PA in the background.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
In your callback you can read audio data from the inputBuffer and/or write
|
||||||
|
data to the outputBuffer.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Stop the stream by returning 1 from your callback, or by calling a stop
|
||||||
|
function.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Close the stream and terminate the library.</li>
|
||||||
|
</ol>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<blockquote>There is also <a href="pa_tut_rw.html">another interface</a>
|
||||||
|
provided that allows you to generate audio in the foreground. You then
|
||||||
|
simply write data to the stream and the tool will not return until it is
|
||||||
|
ready to accept more data. This interface is simpler to use but is usually
|
||||||
|
not preferred for large applications because it requires that you launch
|
||||||
|
a thread to perform the synthesis. Launching a thread may be difficult
|
||||||
|
on non-multi-tasking systems such as the Macintosh prior to MacOS X.
|
||||||
|
<p>Let's continue by building a simple application that will play a sawtooth
|
||||||
|
wave.
|
||||||
|
<p>Please select the page for the specific implementation you would like
|
||||||
|
to use:
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="pa_tut_pc.html">Windows (WMME or DirectSound)</a></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="pa_tut_mac.html">Macintosh SoundManager for OS 7,8,9</a></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="pa_tut_mac_osx.html">Macintosh CoreAudio for OS X</a></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="pa_tut_asio.html">ASIO on Windows or Macintosh</a></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="pa_tut_oss.html">Unix OSS</a></li>
|
||||||
|
</ul>
|
||||||
|
or continue with the <a href="pa_tut_callback.html">next page of the programming
|
||||||
|
tutorial</a>.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tutorial.html">previous</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
78
portaudio-v19/docs/pa_tut_pc.html
Normal file
78
portaudio-v19/docs/pa_tut_pc.html
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Compiling for Windows (WMME or DirectSound)</h2>
|
||||||
|
|
||||||
|
<blockquote>To compile PortAudio for Windows, you can choose between two
|
||||||
|
options. One implementation uses the DirectSound API. The other uses the
|
||||||
|
Windows MultiMedia Extensions API (aka WMME or WAVE).
|
||||||
|
<p>Some advantages of using DirectSound are that DirectSound may have lower
|
||||||
|
latency than WMME, and supports effects processing plugins. But one disadvantage
|
||||||
|
is that DirectSound is not installed on all PCs, and is not well supported
|
||||||
|
under Windows NT. So WMME is the best choice for most projects.
|
||||||
|
<p>For either implementation add the following source files to your project:
|
||||||
|
<blockquote>
|
||||||
|
<pre><b>pa_common\pa_lib.c
|
||||||
|
pa_common\portaudio.h
|
||||||
|
pa_common\pa_host.h</b></pre>
|
||||||
|
</blockquote>
|
||||||
|
Link with the system library "<b>winmm.lib</b>". For Visual C++:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
select "Settings..." from the "Project" menu,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
select the project name in the tree on the left,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
choose "All Configurations" in the popup menu above the tree,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
select the "Link" tab,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
enter "winmm.lib", without quotes, as the first item in the "Object/library
|
||||||
|
modules:" field.</li>
|
||||||
|
</ol>
|
||||||
|
<b>WMME</b> - To use the WMME implementation, add the following source
|
||||||
|
files to your project:
|
||||||
|
<blockquote><b><tt>pa_win_wmme/pa_win_wmme.c</tt></b></blockquote>
|
||||||
|
<b>DirectSound</b> - If you want to use the DirectSound implementation
|
||||||
|
of PortAudio then you must have a recent copy of the free
|
||||||
|
<a href="http://www.microsoft.com/directx/download.asp">DirectX</a>
|
||||||
|
SDK for Developers from Microsoft installed on your computer. To compile
|
||||||
|
an application add the following source files to your project:
|
||||||
|
<blockquote>
|
||||||
|
<pre><b>pa_win_ds\dsound_wrapper.c
|
||||||
|
pa_win_ds\pa_dsound.c</b></pre>
|
||||||
|
</blockquote>
|
||||||
|
Link with the system library "<b>dsound.lib</b>" using the procedure described
|
||||||
|
above for "winmm.lib".</blockquote>
|
||||||
|
|
||||||
|
<blockquote>You might try compiling the "pa_tests\patest_saw.c" file first
|
||||||
|
because it is the simplest.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
56
portaudio-v19/docs/pa_tut_run.html
Normal file
56
portaudio-v19/docs/pa_tut_run.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Starting and Stopping a Stream</h2>
|
||||||
|
|
||||||
|
<blockquote>The stream will not start running until you call Pa_StartStream().
|
||||||
|
Then it will start calling your callback function to perform the audio
|
||||||
|
processing.
|
||||||
|
<blockquote>
|
||||||
|
<pre>err = Pa_StartStream( stream );
|
||||||
|
if( err != paNoError ) goto error;</pre>
|
||||||
|
</blockquote>
|
||||||
|
At this point, audio is being generated. You can communicate to your callback
|
||||||
|
routine through the data structure you passed in on the open call, or through
|
||||||
|
global variables, or using other interprocess communication techniques.
|
||||||
|
Please be aware that your callback function may be called at interrupt
|
||||||
|
time when your foreground process is least expecting it. So avoid sharing
|
||||||
|
complex data structures that are easily corrupted like double linked lists.
|
||||||
|
<p>In many of the tests we simply sleep for a few seconds so we can hear
|
||||||
|
the sound. This is easy to do with Pa_Sleep() which will sleep for some
|
||||||
|
number of milliseconds. Do not rely on this function for accurate scheduling.
|
||||||
|
it is mostly for writing examples.
|
||||||
|
<blockquote>
|
||||||
|
<pre>/* Sleep for several seconds. */
|
||||||
|
Pa_Sleep(NUM_SECONDS*1000);</pre>
|
||||||
|
</blockquote>
|
||||||
|
When you are through, you can stop the stream from the foreground.
|
||||||
|
<blockquote>
|
||||||
|
<pre>err = Pa_StopStream( stream );
|
||||||
|
if( err != paNoError ) goto error;</pre>
|
||||||
|
</blockquote>
|
||||||
|
You can also stop the stream by returning 1 from your custom callback function.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_open.html">previous</a> | <a href="pa_tut_term.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
79
portaudio-v19/docs/pa_tut_rw.html
Normal file
79
portaudio-v19/docs/pa_tut_rw.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Blocking Read/Write Functions</h2>
|
||||||
|
|
||||||
|
<blockquote>[Note: These functions are not part of the official PortAudio
|
||||||
|
API. They are simply built on top of PortAudio as an extra utility. Also
|
||||||
|
note that they are under evaluation and their definition may change.]
|
||||||
|
<p>There are two fundamentally different ways to design an audio API. One
|
||||||
|
is to use callback functions the way we have already shown. The callback
|
||||||
|
function operates under an interrupt or background thread This leaves the
|
||||||
|
foreground application free to do other things while the audio just runs
|
||||||
|
in the background. But this can sometimes be awkward.
|
||||||
|
<p>So we have provided an alternative technique that lets a program generate
|
||||||
|
audio in the foreground and then just write it to the audio stream as if
|
||||||
|
it was a file. If there is not enough room in the audio buffer for more
|
||||||
|
data, then the write function will just block until more room is available.
|
||||||
|
This can make it very easy to write an audio example. To use this tool,
|
||||||
|
you must add the files "pablio/pablio.c" and "pablio/ringbuffer.c" to your
|
||||||
|
project. You must also:
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include "pablio.h"</pre>
|
||||||
|
</blockquote>
|
||||||
|
Here is a short excerpt of a program that opens a stream for input and
|
||||||
|
output. It then reads a block of samples from input, and writes them to
|
||||||
|
output, in a loop. The complete example can be found in "pablio/test_rw.c".
|
||||||
|
<blockquote>
|
||||||
|
<pre> #define SAMPLES_PER_FRAME (2)
|
||||||
|
#define FRAMES_PER_BLOCK (1024)
|
||||||
|
SAMPLE samples[SAMPLES_PER_FRAME * FRAMES_PER_BLOCK];
|
||||||
|
PaError err;
|
||||||
|
PABLIO_Stream *aStream;
|
||||||
|
|
||||||
|
/* Open simplified blocking I/O layer on top of PortAudio. */
|
||||||
|
err = OpenAudioStream( &rwbl, SAMPLE_RATE, paFloat32,
|
||||||
|
(PABLIO_READ_WRITE | PABLIO_STEREO) );
|
||||||
|
if( err != paNoError ) goto error;
|
||||||
|
|
||||||
|
/* Process samples in the foreground. */
|
||||||
|
for( i=0; i<(NUM_SECONDS * SAMPLE_RATE); i++ )
|
||||||
|
{
|
||||||
|
/* Read one block of data into sample array from audio input. */
|
||||||
|
ReadAudioStream( aStream, samples, FRAMES_PER_BLOCK );
|
||||||
|
/*
|
||||||
|
** At this point you could process the data in samples array,
|
||||||
|
** and write the result back to the same samples array.
|
||||||
|
*/
|
||||||
|
/* Write that same frame of data to output. */
|
||||||
|
WriteAudioStream( aStream, samples, FRAMES_PER_BLOCK );
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseAudioStream( aStream );</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_devs.html">previous</a> | <a href="pa_tut_explore.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
47
portaudio-v19/docs/pa_tut_term.html
Normal file
47
portaudio-v19/docs/pa_tut_term.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Terminating PortAudio</h2>
|
||||||
|
|
||||||
|
<blockquote>You can start and stop a stream as many times as you like.
|
||||||
|
But when you are done using it, you should close it by calling:</blockquote>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<pre>err = Pa_CloseStream( stream );
|
||||||
|
if( err != paNoError ) goto error;</pre>
|
||||||
|
</blockquote>
|
||||||
|
Then when you are done using PortAudio, you should terminate the whole
|
||||||
|
system by calling:
|
||||||
|
<blockquote>
|
||||||
|
<pre>Pa_Terminate();</pre>
|
||||||
|
</blockquote>
|
||||||
|
That's basically it. You can now write an audio program in 'C' that will
|
||||||
|
run on multiple platforms, for example PCs and Macintosh.
|
||||||
|
<p>In the rest of the tutorial we will look at some additional utility
|
||||||
|
functions, and a different way of using PortAudio that does not require
|
||||||
|
the use of a callback function.</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
|
||||||
|
| <a href="pa_tut_run.html">previous</a> | <a href="pa_tut_util.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
55
portaudio-v19/docs/pa_tut_util.html
Normal file
55
portaudio-v19/docs/pa_tut_util.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.75 [en]C-gatewaynet (Win98; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Utility Functions</h2>
|
||||||
|
|
||||||
|
<blockquote>Here are several more functions that are not critical, but
|
||||||
|
may be handy when using PortAudio.
|
||||||
|
<p>Pa_StreamActive() returns one when the stream in playing audio, zero
|
||||||
|
when not playing, or a negative error number if the stream is invalid.
|
||||||
|
The stream is active between calls to Pa_StartStream() and Pa_StopStream(),
|
||||||
|
but may also become inactive if the callback returns a non-zero value.
|
||||||
|
In the latter case, the stream is considered inactive after the last buffer
|
||||||
|
has finished playing.
|
||||||
|
<blockquote>
|
||||||
|
<pre>PaError Pa_StreamActive( PortAudioStream *stream );</pre>
|
||||||
|
</blockquote>
|
||||||
|
Pa_StreamTime() returns the number of samples that have been generated.
|
||||||
|
PaTimeStamp is a double precision number which is a convenient way to pass
|
||||||
|
big numbers around even though we only need integers.
|
||||||
|
<blockquote>
|
||||||
|
<pre>PaTimestamp Pa_StreamTime( PortAudioStream *stream );</pre>
|
||||||
|
</blockquote>
|
||||||
|
The "CPU Load" is a fraction of total CPU time consumed by the stream's
|
||||||
|
audio processing. A value of 0.5 would imply that PortAudio and the sound
|
||||||
|
generating callback was consuming roughly 50% of the available CPU time.
|
||||||
|
This function may be called from the callback function or the application.
|
||||||
|
<blockquote>
|
||||||
|
<pre>double Pa_GetCPULoad( PortAudioStream* stream );</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> |
|
||||||
|
<a href="pa_tutorial.html">contents</a> | <a href="pa_tut_term.html">previous</a>
|
||||||
|
| <a href="pa_tut_devs.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
46
portaudio-v19/docs/pa_tutorial.html
Normal file
46
portaudio-v19/docs/pa_tutorial.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Tutorial</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio Tutorial</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<p>Copyright 2000 Phil Burk and Ross Bencina
|
||||||
|
<h2>
|
||||||
|
Table of Contents</h2>
|
||||||
|
|
||||||
|
<blockquote><a href="pa_tut_over.html">Overview of PortAudio</a>
|
||||||
|
<br><a href="pa_tut_mac.html">Compiling for Macintosh OS 7,8,9</a>
|
||||||
|
<br><a href="pa_tut_mac_osx.html">Compiling for Macintosh OS X</a>
|
||||||
|
<br><a href="pa_tut_pc.html">Compiling for Windows (DirectSound and WMME)</a>
|
||||||
|
<br><a href="pa_tut_asio.html">Compiling for ASIO on Windows or Mac OS
|
||||||
|
8,9</a>
|
||||||
|
<br><a href="pa_tut_oss.html">Compiling for Unix OSS</a>
|
||||||
|
<br><a href="pa_tut_callback.html">Writing a Callback Function</a>
|
||||||
|
<br><a href="pa_tut_init.html">Initializing PortAudio</a>
|
||||||
|
<br><a href="pa_tut_open.html">Opening a Stream using Defaults</a>
|
||||||
|
<br><a href="pa_tut_run.html">Starting and Stopping a Stream</a>
|
||||||
|
<br><a href="pa_tut_term.html">Cleaning Up</a>
|
||||||
|
<br><a href="pa_tut_util.html">Utilities</a>
|
||||||
|
<br><a href="pa_tut_devs.html">Querying for Devices</a>
|
||||||
|
<br><a href="pa_tut_rw.html">Blocking Read/Write Functions</a>
|
||||||
|
<br><a href="pa_tut_explore.html">Exploring the PortAudio Package</a></blockquote>
|
||||||
|
<font size=+2><a href="http://www.portaudio.com/">home</a> | contents |
|
||||||
|
previous | <a href="pa_tut_over.html">next</a></font>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
425
portaudio-v19/docs/portaudio_h.txt
Normal file
425
portaudio-v19/docs/portaudio_h.txt
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
#ifndef PORT_AUDIO_H
|
||||||
|
#define PORT_AUDIO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* PortAudio API Header File
|
||||||
|
* Latest version available at: 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int PaError;
|
||||||
|
typedef enum {
|
||||||
|
paNoError = 0,
|
||||||
|
|
||||||
|
paHostError = -10000,
|
||||||
|
paInvalidChannelCount,
|
||||||
|
paInvalidSampleRate,
|
||||||
|
paInvalidDeviceId,
|
||||||
|
paInvalidFlag,
|
||||||
|
paSampleFormatNotSupported,
|
||||||
|
paBadIODeviceCombination,
|
||||||
|
paInsufficientMemory,
|
||||||
|
paBufferTooBig,
|
||||||
|
paBufferTooSmall,
|
||||||
|
paNullCallback,
|
||||||
|
paBadStreamPtr,
|
||||||
|
paTimedOut,
|
||||||
|
paInternalError
|
||||||
|
} PaErrorNum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_Initialize() is the library initialisation function - call this before
|
||||||
|
using the library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_Initialize( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_Terminate() is the library termination function - call this after
|
||||||
|
using the library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_Terminate( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return host specific error.
|
||||||
|
This can be called after receiving a paHostError.
|
||||||
|
*/
|
||||||
|
long Pa_GetHostError( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translate the error number into a human readable message.
|
||||||
|
*/
|
||||||
|
const char *Pa_GetErrorText( PaError errnum );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sample formats
|
||||||
|
|
||||||
|
These are formats used to pass sound data between the callback and the
|
||||||
|
stream. Each device has a "native" format which may be used when optimum
|
||||||
|
efficiency or control over conversion is required.
|
||||||
|
|
||||||
|
Formats marked "always available" are supported (emulated) by all devices.
|
||||||
|
|
||||||
|
The floating point representation uses +1.0 and -1.0 as the respective
|
||||||
|
maximum and minimum.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef unsigned long PaSampleFormat;
|
||||||
|
#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/
|
||||||
|
#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/
|
||||||
|
#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/
|
||||||
|
#define paInt24 ((PaSampleFormat) (1<<3))
|
||||||
|
#define paPackedInt24 ((PaSampleFormat) (1<<4))
|
||||||
|
#define paInt8 ((PaSampleFormat) (1<<5))
|
||||||
|
#define paUInt8 ((PaSampleFormat) (1<<6)) /* unsigned 8 bit, 128 is "ground" */
|
||||||
|
#define paCustomFormat ((PaSampleFormat) (1<<16))
|
||||||
|
|
||||||
|
/*
|
||||||
|
Device enumeration mechanism.
|
||||||
|
|
||||||
|
Device ids range from 0 to Pa_CountDevices()-1.
|
||||||
|
|
||||||
|
Devices may support input, output or both. Device 0 is always the "default"
|
||||||
|
device and should support at least stereo in and out if that is available
|
||||||
|
on the taget platform _even_ if this involves kludging an input/output
|
||||||
|
device on platforms that usually separate input from output. Other platform
|
||||||
|
specific devices are specified by positive device ids.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int PaDeviceID;
|
||||||
|
#define paNoDevice -1
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int structVersion;
|
||||||
|
const char *name;
|
||||||
|
int maxInputChannels;
|
||||||
|
int maxOutputChannels;
|
||||||
|
/* Number of discrete rates, or -1 if range supported. */
|
||||||
|
int numSampleRates;
|
||||||
|
/* Array of supported sample rates, or {min,max} if range supported. */
|
||||||
|
const double *sampleRates;
|
||||||
|
PaSampleFormat nativeSampleFormats;
|
||||||
|
} PaDeviceInfo;
|
||||||
|
|
||||||
|
|
||||||
|
int Pa_CountDevices();
|
||||||
|
/*
|
||||||
|
Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID()
|
||||||
|
|
||||||
|
Return the default device ID or paNoDevice if there is no devices.
|
||||||
|
The result can be passed to Pa_OpenStream().
|
||||||
|
|
||||||
|
On the PC, the user can specify a default device by
|
||||||
|
setting an environment variable. For example, to use device #1.
|
||||||
|
|
||||||
|
set PA_RECOMMENDED_OUTPUT_DEVICE=1
|
||||||
|
|
||||||
|
The user should first determine the available device ID by using
|
||||||
|
the supplied application "pa_devs".
|
||||||
|
*/
|
||||||
|
PaDeviceID Pa_GetDefaultInputDeviceID( void );
|
||||||
|
PaDeviceID Pa_GetDefaultOutputDeviceID( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
PaTimestamp is used to represent a continuous sample clock with arbitrary
|
||||||
|
start time useful for syncronisation. The type is used in the outTime
|
||||||
|
argument to the callback function and the result of Pa_StreamTime()
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef double PaTimestamp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure
|
||||||
|
referring to the device specified by id.
|
||||||
|
If id is out of range the function returns NULL.
|
||||||
|
|
||||||
|
The returned structure is owned by the PortAudio implementation and must
|
||||||
|
not be manipulated or freed. The pointer is guaranteed to be valid until
|
||||||
|
between calls to Pa_Initialize() and Pa_Terminate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID devID );
|
||||||
|
|
||||||
|
/*
|
||||||
|
PortAudioCallback is implemented by clients of the portable audio api.
|
||||||
|
|
||||||
|
inputBuffer and outputBuffer are arrays of interleaved samples,
|
||||||
|
the format, packing and number of channels used by the buffers are
|
||||||
|
determined by parameters to Pa_OpenStream() (see below).
|
||||||
|
|
||||||
|
framesPerBuffer is the number of sample frames to be processed by the callback.
|
||||||
|
|
||||||
|
outTime is the time in samples when the buffer(s) processed by
|
||||||
|
this callback will begin being played at the audio output.
|
||||||
|
See also Pa_StreamTime()
|
||||||
|
|
||||||
|
userData is the value of a user supplied pointer passed to Pa_OpenStream()
|
||||||
|
intended for storing synthesis data etc.
|
||||||
|
|
||||||
|
return value:
|
||||||
|
The callback can return a nonzero value to stop the stream. This may be
|
||||||
|
useful in applications such as soundfile players where a specific duration
|
||||||
|
of output is required. However, it is not necessary to utilise this mechanism
|
||||||
|
as StopStream() will also terminate the stream. A callback returning a
|
||||||
|
nonzero value must fill the entire outputBuffer.
|
||||||
|
|
||||||
|
NOTE: None of the other stream functions may be called from within the
|
||||||
|
callback function except for Pa_GetCPULoad().
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int (PortAudioCallback)(
|
||||||
|
void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaTimestamp outTime, void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Stream flags
|
||||||
|
|
||||||
|
These flags may be supplied (ored together) in the streamFlags argument to
|
||||||
|
the Pa_OpenStream() function.
|
||||||
|
|
||||||
|
[ suggestions? ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define paNoFlag (0)
|
||||||
|
#define paClipOff (1<<0) /* disable defult clipping of out of range samples */
|
||||||
|
#define paDitherOff (1<<1) /* disable default dithering */
|
||||||
|
#define paPlatformSpecificFlags (0x00010000)
|
||||||
|
typedef unsigned long PaStreamFlags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
A single PortAudioStream provides multiple channels of real-time
|
||||||
|
input and output audio streaming to a client application.
|
||||||
|
Pointers to PortAudioStream objects are passed between PortAudio functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void PortAudioStream;
|
||||||
|
#define PaStream PortAudioStream
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_OpenStream() opens a stream for either input, output or both.
|
||||||
|
|
||||||
|
stream is the address of a PortAudioStream pointer which will receive
|
||||||
|
a pointer to the newly opened stream.
|
||||||
|
|
||||||
|
inputDevice is the id of the device used for input (see PaDeviceID above.)
|
||||||
|
inputDevice may be paNoDevice to indicate that an input device is not required.
|
||||||
|
|
||||||
|
numInputChannels is the number of channels of sound to be delivered to the
|
||||||
|
callback. It can range from 1 to the value of maxInputChannels in the
|
||||||
|
device input record for the device specified in the inputDevice parameter.
|
||||||
|
If inputDevice is paNoDevice numInputChannels is ignored.
|
||||||
|
|
||||||
|
inputSampleFormat is the format of inputBuffer provided to the callback
|
||||||
|
function. inputSampleFormat may be any of the formats described by the
|
||||||
|
PaSampleFormat enumeration (see above). PortAudio guarantees support for
|
||||||
|
the sound devices native formats (nativeSampleFormats in the device info
|
||||||
|
record) and additionally 16 and 32 bit integer and 32 bit floating point
|
||||||
|
formats. Support for other formats is implementation defined.
|
||||||
|
|
||||||
|
inputDriverInfo is a pointer to an optional driver specific data structure
|
||||||
|
containing additional information for device setup or stream processing.
|
||||||
|
inputDriverInfo is never required for correct operation. If not used
|
||||||
|
inputDriverInfo should be NULL.
|
||||||
|
|
||||||
|
outputDevice is the id of the device used for output (see PaDeviceID above.)
|
||||||
|
outputDevice may be paNoDevice to indicate that an output device is not required.
|
||||||
|
|
||||||
|
numOutputChannels is the number of channels of sound to be supplied by the
|
||||||
|
callback. See the definition of numInputChannels above for more details.
|
||||||
|
|
||||||
|
outputSampleFormat is the sample format of the outputBuffer filled by the
|
||||||
|
callback function. See the definition of inputSampleFormat above for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
outputDriverInfo is a pointer to an optional driver specific data structure
|
||||||
|
containing additional information for device setup or stream processing.
|
||||||
|
outputDriverInfo is never required for correct operation. If not used
|
||||||
|
outputDriverInfo should be NULL.
|
||||||
|
|
||||||
|
sampleRate is the desired sampleRate for input and output
|
||||||
|
|
||||||
|
framesPerBuffer is the length in sample frames of all internal sample buffers
|
||||||
|
used for communication with platform specific audio routines. Wherever
|
||||||
|
possible this corresponds to the framesPerBuffer parameter passed to the
|
||||||
|
callback function.
|
||||||
|
|
||||||
|
numberOfBuffers is the number of buffers used for multibuffered
|
||||||
|
communication with the platform specific audio routines. This parameter is
|
||||||
|
provided only as a guide - and does not imply that an implementation must
|
||||||
|
use multibuffered i/o when reliable double buffering is available (such as
|
||||||
|
SndPlayDoubleBuffer() on the Macintosh.)
|
||||||
|
|
||||||
|
streamFlags may contain a combination of flags ORed together.
|
||||||
|
These flags modify the behavior of the
|
||||||
|
streaming process. Some flags may only be relevant to certain buffer formats.
|
||||||
|
|
||||||
|
callback is a pointer to a client supplied function that is responsible
|
||||||
|
for processing and filling input and output buffers (see above for details.)
|
||||||
|
|
||||||
|
userData is a client supplied pointer which is passed to the callback
|
||||||
|
function. It could for example, contain a pointer to instance data necessary
|
||||||
|
for processing the audio buffers.
|
||||||
|
|
||||||
|
return value:
|
||||||
|
Apon success Pa_OpenStream() returns PaNoError and places a pointer to a
|
||||||
|
valid PortAudioStream in the stream argument. The stream is inactive (stopped).
|
||||||
|
If a call to Pa_OpenStream() fails a nonzero error code is returned (see
|
||||||
|
PAError above) and the value of stream is invalid.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_OpenStream( PortAudioStream** stream,
|
||||||
|
PaDeviceID inputDevice,
|
||||||
|
int numInputChannels,
|
||||||
|
PaSampleFormat inputSampleFormat,
|
||||||
|
void *inputDriverInfo,
|
||||||
|
PaDeviceID outputDevice,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat outputSampleFormat,
|
||||||
|
void *outputDriverInfo,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that
|
||||||
|
opens the default input and/or ouput devices. Most parameters have
|
||||||
|
identical meaning to their Pa_OpenStream() counterparts, with the following
|
||||||
|
exceptions:
|
||||||
|
|
||||||
|
If either numInputChannels or numOutputChannels is 0 the respective device
|
||||||
|
is not opened (same as passing paNoDevice in the device arguments to Pa_OpenStream() )
|
||||||
|
|
||||||
|
sampleFormat applies to both the input and output buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_OpenDefaultStream( PortAudioStream** stream,
|
||||||
|
int numInputChannels,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat sampleFormat,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_CloseStream() closes an audio stream, flushing any pending buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_CloseStream( PortAudioStream* );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_StartStream() and Pa_StopStream() begin and terminate audio processing.
|
||||||
|
Pa_StopStream() waits until all pending audio buffers have been played.
|
||||||
|
Pa_AbortStream() stops playing immediately without waiting for pending
|
||||||
|
buffers to complete.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_StartStream( PortAudioStream *stream );
|
||||||
|
|
||||||
|
PaError Pa_StopStream( PortAudioStream *stream );
|
||||||
|
|
||||||
|
PaError Pa_AbortStream( PortAudioStream *stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_StreamActive() returns one when the stream is playing audio,
|
||||||
|
zero when not playing, or a negative error number if the
|
||||||
|
stream is invalid.
|
||||||
|
The stream is active between calls to Pa_StartStream() and Pa_StopStream(),
|
||||||
|
but may also become inactive if the callback returns a non-zero value.
|
||||||
|
In the latter case, the stream is considered inactive after the last
|
||||||
|
buffer has finished playing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError Pa_StreamActive( PortAudioStream *stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_StreamTime() returns the current output time for the stream in samples.
|
||||||
|
This time may be used as a time reference (for example syncronising audio to
|
||||||
|
MIDI).
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaTimestamp Pa_StreamTime( PortAudioStream *stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
The "CPU Load" is a fraction of total CPU time consumed by the
|
||||||
|
stream's audio processing.
|
||||||
|
A value of 0.5 would imply that PortAudio and the sound generating
|
||||||
|
callback was consuming roughly 50% of the available CPU time.
|
||||||
|
This function may be called from the callback function or the application.
|
||||||
|
*/
|
||||||
|
double Pa_GetCPULoad( PortAudioStream* stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Use Pa_GetMinNumBuffers() to determine minimum number of buffers required for
|
||||||
|
the current host based on minimum latency.
|
||||||
|
On the PC, for the DirectSound implementation, latency can be optionally set
|
||||||
|
by user by setting an environment variable.
|
||||||
|
For example, to set latency to 200 msec, put:
|
||||||
|
|
||||||
|
set PA_MIN_LATENCY_MSEC=200
|
||||||
|
|
||||||
|
in the AUTOEXEC.BAT file and reboot.
|
||||||
|
If the environment variable is not set, then the latency will be determined
|
||||||
|
based on the OS. Windows NT has higher latency than Win95.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sleep for at least 'msec' milliseconds.
|
||||||
|
You may sleep longer than the requested time so don't rely
|
||||||
|
on this for accurate musical timing.
|
||||||
|
*/
|
||||||
|
void Pa_Sleep( long msec );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return size in bytes of a single sample in a given PaSampleFormat
|
||||||
|
or paSampleFormatNotSupported.
|
||||||
|
*/
|
||||||
|
PaError Pa_GetSampleSize( PaSampleFormat format );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PORT_AUDIO_H */
|
||||||
BIN
portaudio-v19/docs/portaudio_icmc2001.pdf
Normal file
BIN
portaudio-v19/docs/portaudio_icmc2001.pdf
Normal file
Binary file not shown.
36
portaudio-v19/docs/proposals.html
Normal file
36
portaudio-v19/docs/proposals.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Proposed Changes to PortAudio API</TITLE>
|
||||||
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
|
||||||
|
<META content="Phil Burk, Ross Bencina" name=Author>
|
||||||
|
<META content="Changes being discussed by the community of PortAudio deveopers."
|
||||||
|
name=Description>
|
||||||
|
<META
|
||||||
|
content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,"
|
||||||
|
name=KeyWords>
|
||||||
|
</HEAD>
|
||||||
|
<BODY LINK="#0000ff" VLINK="#800080">
|
||||||
|
<CENTER>
|
||||||
|
<TABLE bgColor=#fada7a cols=1 width="100%">
|
||||||
|
<TBODY>
|
||||||
|
<TR>
|
||||||
|
<TD>
|
||||||
|
<CENTER>
|
||||||
|
<H1>Proposed Changes to PortAudio API</H1>
|
||||||
|
</CENTER>
|
||||||
|
</TD></TR></TBODY></TABLE></CENTER>
|
||||||
|
<P><A href="http://www.portaudio.com/">PortAudio Home Page</A></P>
|
||||||
|
|
||||||
|
<P>Updated: July 27, 2002 </P>
|
||||||
|
<H2>The Proposals Have Moved</H2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
All PortAudio Enhancement Proposal documentation has moved. On the web site, it is now located at:
|
||||||
|
<A HREF="http://www.portaudio.com/docs/proposals">http://www.portaudio.com/docs/proposals</A>
|
||||||
|
|
||||||
|
On the CVS server it is now located in a module named "pa_proposals".
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
339
portaudio-v19/docs/releases.html
Normal file
339
portaudio-v19/docs/releases.html
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="PortAudio is a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Release Notes</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio - Release Notes</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<p>Link to <a href="http://www.portaudio.com">PortAudio Home Page</a>
|
||||||
|
<h2>
|
||||||
|
<b>V18 - 5/6/02</b></h2>
|
||||||
|
|
||||||
|
<blockquote>All source code and documentation now under <a href="http://www.portaudio.com/usingcvs.html">CVS</a>.
|
||||||
|
<p>Ran most of the code through <a href="http://astyle.sourceforge.net/">AStyle</a>
|
||||||
|
to cleanup ragged indentation caused by using different editors. Used this
|
||||||
|
command:
|
||||||
|
<br><tt> astyle --style=ansi -c -o --convert-tabs --indent-preprocessor
|
||||||
|
*.c</tt></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Added "pa_common/pa_convert.c" for Mac OS X. Start of new conversion
|
||||||
|
utilities.
|
||||||
|
<p><b>ASIO</b>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
New Pa_ASIO_Adaptor_Init function to init Callback adpatation variables,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Cleanup of Pa_ASIO_Callback_Input</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Break apart device loading to debug random failure in Pa_ASIO_QueryDeviceInfo</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Deallocate all resources in PaHost_Term for cases where Pa_CloseStream
|
||||||
|
is not called properly</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
New Pa_ASIO_loadDriver that calls CoInitialize on each thread on Windows.
|
||||||
|
Allows use by multiple threads.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Correct error code management in PaHost_Term, removed various compiler
|
||||||
|
warning</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Add Mac includes for <Devices.h> and <Timer.h></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Pa_ASIO_QueryDeviceInfo bug correction, memory allocation checking, better
|
||||||
|
error handling</li>
|
||||||
|
</ul>
|
||||||
|
<b>Mac OS X</b>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Major cleanup and improvements.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Fixed device queries for numChannels and sampleRates,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Audio input works if using same CoreAudio device (some HW devices make
|
||||||
|
separate CoreAudio devices).</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added paInt16, paInt8, format using new "pa_common/pa_convert.c" file.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Return error if opened in mono mode cuz not supported.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Check for getenv("PA_MIN_LATEWNCY_MSEC") to set latency externally.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Use getrusage() instead of gettimeofday() for CPU Load calculation.</li>
|
||||||
|
</ul>
|
||||||
|
<b>Windows MME</b>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Fixed bug that caused TIMEOUT in Pa_StopStream(). Added check for past_StopSoon()
|
||||||
|
in Pa_TimeSlice(). Thanks Julien Maillard.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Detect Win XP versus NT, use lower latency.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Fix DBUG typo;</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
removed init of CurrentCount which was not compiling on Borland</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
general cleanup, factored streamData alloc and cpu usage initialization</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
stopped counting WAVE_MAPPER when there were no audio cards plugged in</li>
|
||||||
|
</ul>
|
||||||
|
<b>Windows DirectSound</b>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Detect Win XP and Win 2K properly when determining latency.</li>
|
||||||
|
</ul>
|
||||||
|
<b>Unix OSS</b>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Use high real-time priority if app is running with root priveledges. Lowers
|
||||||
|
latency.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added watch dog thread that prevents real-time thread from hogging CPU
|
||||||
|
and hanging the computer.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Check error return from read() and write().</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Check CPU endianness instead of assuming Little Endian.</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b>V17 - 10/15/01</b></h2>
|
||||||
|
|
||||||
|
<blockquote><b>Unix OSS</b>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Set num channels back to two after device query for ALSA. This fixed a
|
||||||
|
bug in V16 that sometimes caused a failure when querying for the sample
|
||||||
|
rates. Thanks Stweart Greenhill.</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<h4>
|
||||||
|
<b>Macintosh Sound Manager</b></h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Use NewSndCallBackUPP() for CARBON compatibility.</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b>V16 - 9/27/01</b></h2>
|
||||||
|
|
||||||
|
<blockquote><b>Added Alpha implementations for ASIO, SGI, and BeOS!</b>
|
||||||
|
<br>
|
||||||
|
<li>
|
||||||
|
CPULoad is now calculated based on the time spent to generate a known number
|
||||||
|
of frames. This is more accurate than a simple percentage of real-time.
|
||||||
|
Implemented in pa_unix_oss, pa_win_wmme and pa_win_ds.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Fix dither and shift for recording PaUInt8 format data.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added "patest_maxsines.c" which tests <tt>Pa_GetCPULoad().</tt></li>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<h4>
|
||||||
|
Windows WMME</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
sDevicePtrs now allocated using <tt>GlobalAlloc()</tt>. This prevents a
|
||||||
|
crash in Pa_Terminate() on Win2000. Thanks Mike Berry for finding this.
|
||||||
|
Thanks Mike Berry.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Pass process instead of thread to <tt>SetPriorityClass</tt>(). This fixes
|
||||||
|
a bug that caused the priority to not be increased. Thanks to Alberto di
|
||||||
|
Bene for spotting this.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
Windows DirectSound</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Casts for compiling with __MWERKS__ CodeWarrior.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
UNIX OSS</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Derived from Linux OSS implementation.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Numerous patches from Heiko Purnhagen, Stephen Brandon, etc.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Improved query mechanism which often bailed out unnecessarily.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Removed sNumDevices and potential related bugs,</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Use <tt>getenv("PA_MIN_LATENCY_MSEC")</tt> in code to set desired latency.
|
||||||
|
User can set by entering:</li>
|
||||||
|
|
||||||
|
<br> <tt>export PA_MIN_LATENCY_MSEC=40</tt></ul>
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
Macintosh Sound Manager</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Pass unused event to WaitNextEvent instead of NULL to prevent Mac OSX crash.
|
||||||
|
Thanks Dominic Mazzoni.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Use requested number of input channels.</li>
|
||||||
|
|
||||||
|
<br> </ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b>V15 - 5/29/01</b></h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<b>New Linux OSS Beta</b></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
Windows WMME</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
sDevicePtrs now allocated based on sizeof(pointer). Was allocating
|
||||||
|
too much space.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Check for excessive numbers of channels. Some drivers reported bogus
|
||||||
|
numbers.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Apply Mike Berry's changes for CodeWarrior on PC including condition including
|
||||||
|
of memory.h, and explicit typecasting on memory allocation.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
Macintosh Sound Manager</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
ScanInputDevices was setting sDefaultOutputDeviceID instead of sDefaultInputDeviceID.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Device Scan was crashing for anything other than siBadSoundInDevice, but
|
||||||
|
some Macs may return other errors! Caused failure to init on some G4s under
|
||||||
|
OS9.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Fix TIMEOUT in record mode.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Change CARBON_COMPATIBLE to TARGET_API_MAC_CARBON</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b>V14 - 2/6/01</b></h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Added implementation for Windows MultiMedia Extensions (WMME) by Ross and
|
||||||
|
Phil</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Changed Pa_StopStream() so that it waits for the buffers to drain.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added Pa_AbortStream() that stops immediately without waiting.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added new test: patest_stop.c to test above two mods.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Fixed Pa_StreamTime() so that it returns current play position instead
|
||||||
|
of the write position. Added "patest_sync.c" to demo audio/video sync.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Improved stability of Macintosh implementation. Added timeouts to prevent
|
||||||
|
hangs.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added Pa_GetSampleSize( PaSampleFormat format );</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Changes some "int"s to "long"s so that PA works properly on Macintosh which
|
||||||
|
often compiles using 16 bit ints.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Added Implementation Guide</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b>V12 - 1/9/01</b></h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Mac now scans for and queries all devices. But it does not yet support
|
||||||
|
selecting any other than the default device.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Blocking I/O calls renamed to separate them from the PortAudio API.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Cleaned up indentation problems with tabs versus spaces.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Now attempts to correct bogus sample rate info returned from DirectSound
|
||||||
|
device queries.</li>
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
19
portaudio-v19/fixdir.bat
Executable file
19
portaudio-v19/fixdir.bat
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
rem Use Astyle to fix style in 'C' files
|
||||||
|
cd %1%
|
||||||
|
|
||||||
|
fixlines -p *.c
|
||||||
|
fixlines -p *.cpp
|
||||||
|
fixlines -p *.cc
|
||||||
|
|
||||||
|
astyle --style=ansi -c -o --convert-tabs --indent-preprocessor *.c
|
||||||
|
astyle --style=ansi -c -o --convert-tabs --indent-preprocessor *.cpp
|
||||||
|
astyle --style=ansi -c -o --convert-tabs --indent-preprocessor *.cc
|
||||||
|
del *.orig
|
||||||
|
@rem convert line terminators to Unix style LFs
|
||||||
|
fixlines -u *.c
|
||||||
|
fixlines -u *.cpp
|
||||||
|
fixlines -u *.cc
|
||||||
|
fixlines -u *.h
|
||||||
|
del *.bak
|
||||||
|
|
||||||
|
cd ..\
|
||||||
7
portaudio-v19/fixfile.bat
Executable file
7
portaudio-v19/fixfile.bat
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
rem Use Astyle to fix style in a file
|
||||||
|
fixlines -p %1%
|
||||||
|
astyle --style=ansi -c -o --convert-tabs --indent-preprocessor %1%
|
||||||
|
del %1%.orig
|
||||||
|
@rem convert line terminators to Unix style LFs
|
||||||
|
fixlines -u %1%
|
||||||
|
del %1%.bak
|
||||||
89
portaudio-v19/index.html
Normal file
89
portaudio-v19/index.html
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
|
||||||
|
<meta name="Author" content="Phil Burk">
|
||||||
|
<meta name="Description" content="PortAudio is a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
|
||||||
|
<meta name="KeyWords" content="audio, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
|
||||||
|
<title>PortAudio Implementations for DirectSound</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<h1>
|
||||||
|
PortAudio - Portable Audio Library</h1></center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<p>Last updated 5/6/02.
|
||||||
|
<p>PortAudio is a cross platform, <a href="#License">open-source</a>, audio
|
||||||
|
I/O library proposed by <b>Ross Bencina</b> to the <a href="http://shoko.calarts.edu/~glmrboy/musicdsp/music-dsp.html">music-dsp</a>
|
||||||
|
mailing list. It lets you write simple audio programs in 'C' that will
|
||||||
|
compile and run on <b>Windows, Macintosh, Unix, BeOS</b>. PortAudio is
|
||||||
|
intended to promote the exchange of audio synthesis software between developers
|
||||||
|
on different platforms.
|
||||||
|
<p>For complete information on PortAudio and to download the latest releases,
|
||||||
|
please visit "<b><font size=+2><a href="http://www.portaudio.com">http://www.portaudio.com</a></font></b>".
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<center>
|
||||||
|
<h2>
|
||||||
|
<b><a href="docs/index.html">Click here for Documentation</a></b></h2></center>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b><font size=+2></font></b></h2>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<b><font size=+2>Contacts and E-Mail List</font></b></h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
If you are using or implementing PortAudio then please join the <b><font size=+1><a href="http://techweb.rfa.org/mailman/listinfo/portaudio">PortAudio
|
||||||
|
mail list</a></font><font size=+2> </font></b>generously administered by
|
||||||
|
<b>Bill
|
||||||
|
Eldridge</b>.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
If you find bugs in one of these implementations, or have suggestions,
|
||||||
|
please e-mail them to <a href="mailto:philburk@softsynth.com">Phil Burk</a>.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
If you make improvements to the library, please send them to us so we can
|
||||||
|
incorporate the improvements.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a NAME="License"></a>License</h2>
|
||||||
|
PortAudio Portable Real-Time Audio Library
|
||||||
|
<br>Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||||
|
<p>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:
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
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.</li>
|
||||||
|
</ul>
|
||||||
|
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 ON INFRINGEMENT.
|
||||||
|
<br>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.
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
251
portaudio-v19/install-sh
Executable file
251
portaudio-v19/install-sh
Executable file
@ -0,0 +1,251 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||||
|
#
|
||||||
|
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
# documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
# the above copyright notice appear in all copies and that both that
|
||||||
|
# copyright notice and this permission notice appear in supporting
|
||||||
|
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||||
|
# publicity pertaining to distribution of the software without specific,
|
||||||
|
# written prior permission. M.I.T. makes no representations about the
|
||||||
|
# suitability of this software for any purpose. It is provided "as is"
|
||||||
|
# without express or implied warranty.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# `make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch. It can only install one file at a time, a restriction
|
||||||
|
# shared with many OS's install programs.
|
||||||
|
|
||||||
|
|
||||||
|
# set DOITPROG to echo to test this script
|
||||||
|
|
||||||
|
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||||
|
doit="${DOITPROG-}"
|
||||||
|
|
||||||
|
|
||||||
|
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||||
|
|
||||||
|
mvprog="${MVPROG-mv}"
|
||||||
|
cpprog="${CPPROG-cp}"
|
||||||
|
chmodprog="${CHMODPROG-chmod}"
|
||||||
|
chownprog="${CHOWNPROG-chown}"
|
||||||
|
chgrpprog="${CHGRPPROG-chgrp}"
|
||||||
|
stripprog="${STRIPPROG-strip}"
|
||||||
|
rmprog="${RMPROG-rm}"
|
||||||
|
mkdirprog="${MKDIRPROG-mkdir}"
|
||||||
|
|
||||||
|
transformbasename=""
|
||||||
|
transform_arg=""
|
||||||
|
instcmd="$mvprog"
|
||||||
|
chmodcmd="$chmodprog 0755"
|
||||||
|
chowncmd=""
|
||||||
|
chgrpcmd=""
|
||||||
|
stripcmd=""
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
mvcmd="$mvprog"
|
||||||
|
src=""
|
||||||
|
dst=""
|
||||||
|
dir_arg=""
|
||||||
|
|
||||||
|
while [ x"$1" != x ]; do
|
||||||
|
case $1 in
|
||||||
|
-c) instcmd="$cpprog"
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-d) dir_arg=true
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-m) chmodcmd="$chmodprog $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-s) stripcmd="$stripprog"
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
*) if [ x"$src" = x ]
|
||||||
|
then
|
||||||
|
src=$1
|
||||||
|
else
|
||||||
|
# this colon is to work around a 386BSD /bin/sh bug
|
||||||
|
:
|
||||||
|
dst=$1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ x"$src" = x ]
|
||||||
|
then
|
||||||
|
echo "install: no input file specified"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$dir_arg" != x ]; then
|
||||||
|
dst=$src
|
||||||
|
src=""
|
||||||
|
|
||||||
|
if [ -d $dst ]; then
|
||||||
|
instcmd=:
|
||||||
|
chmodcmd=""
|
||||||
|
else
|
||||||
|
instcmd=mkdir
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
|
||||||
|
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
|
||||||
|
if [ -f $src -o -d $src ]
|
||||||
|
then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
echo "install: $src does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$dst" = x ]
|
||||||
|
then
|
||||||
|
echo "install: no destination specified"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename; if your system
|
||||||
|
# does not like double slashes in filenames, you may need to add some logic
|
||||||
|
|
||||||
|
if [ -d $dst ]
|
||||||
|
then
|
||||||
|
dst="$dst"/`basename $src`
|
||||||
|
else
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
## this sed command emulates the dirname command
|
||||||
|
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||||
|
|
||||||
|
# Make sure that the destination directory exists.
|
||||||
|
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||||
|
|
||||||
|
# Skip lots of stat calls in the usual case.
|
||||||
|
if [ ! -d "$dstdir" ]; then
|
||||||
|
defaultIFS='
|
||||||
|
'
|
||||||
|
IFS="${IFS-${defaultIFS}}"
|
||||||
|
|
||||||
|
oIFS="${IFS}"
|
||||||
|
# Some sh's can't handle IFS=/ for some reason.
|
||||||
|
IFS='%'
|
||||||
|
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||||
|
IFS="${oIFS}"
|
||||||
|
|
||||||
|
pathcomp=''
|
||||||
|
|
||||||
|
while [ $# -ne 0 ] ; do
|
||||||
|
pathcomp="${pathcomp}${1}"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ ! -d "${pathcomp}" ] ;
|
||||||
|
then
|
||||||
|
$mkdirprog "${pathcomp}"
|
||||||
|
else
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
|
||||||
|
pathcomp="${pathcomp}/"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$dir_arg" != x ]
|
||||||
|
then
|
||||||
|
$doit $instcmd $dst &&
|
||||||
|
|
||||||
|
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||||
|
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||||
|
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||||
|
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||||
|
else
|
||||||
|
|
||||||
|
# If we're going to rename the final executable, determine the name now.
|
||||||
|
|
||||||
|
if [ x"$transformarg" = x ]
|
||||||
|
then
|
||||||
|
dstfile=`basename $dst`
|
||||||
|
else
|
||||||
|
dstfile=`basename $dst $transformbasename |
|
||||||
|
sed $transformarg`$transformbasename
|
||||||
|
fi
|
||||||
|
|
||||||
|
# don't allow the sed command to completely eliminate the filename
|
||||||
|
|
||||||
|
if [ x"$dstfile" = x ]
|
||||||
|
then
|
||||||
|
dstfile=`basename $dst`
|
||||||
|
else
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make a temp file name in the proper directory.
|
||||||
|
|
||||||
|
dsttmp=$dstdir/#inst.$$#
|
||||||
|
|
||||||
|
# Move or copy the file name to the temp name
|
||||||
|
|
||||||
|
$doit $instcmd $src $dsttmp &&
|
||||||
|
|
||||||
|
trap "rm -f ${dsttmp}" 0 &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits
|
||||||
|
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||||
|
|
||||||
|
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||||
|
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||||
|
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||||
|
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
|
||||||
|
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||||
|
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||||
|
|
||||||
|
fi &&
|
||||||
|
|
||||||
|
|
||||||
|
exit 0
|
||||||
137
portaudio-v19/pa_asio/ASIO-README.txt
Normal file
137
portaudio-v19/pa_asio/ASIO-README.txt
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
BIN
portaudio-v19/pa_asio/Callback_adaptation_.pdf
Normal file
BIN
portaudio-v19/pa_asio/Callback_adaptation_.pdf
Normal file
Binary file not shown.
BIN
portaudio-v19/pa_asio/Pa_ASIO.pdf
Normal file
BIN
portaudio-v19/pa_asio/Pa_ASIO.pdf
Normal file
Binary file not shown.
563
portaudio-v19/pa_asio/iasiothiscallresolver.cpp
Normal file
563
portaudio-v19/pa_asio/iasiothiscallresolver.cpp
Normal file
@ -0,0 +1,563 @@
|
|||||||
|
/*
|
||||||
|
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 */
|
||||||
|
|
||||||
197
portaudio-v19/pa_asio/iasiothiscallresolver.h
Normal file
197
portaudio-v19/pa_asio/iasiothiscallresolver.h
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
// ****************************************************************************
|
||||||
|
// 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 */
|
||||||
|
|
||||||
|
|
||||||
2958
portaudio-v19/pa_asio/pa_asio.cpp
Normal file
2958
portaudio-v19/pa_asio/pa_asio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
122
portaudio-v19/pa_asio/pa_asio.h
Normal file
122
portaudio-v19/pa_asio/pa_asio.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#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 */
|
||||||
538
portaudio-v19/pa_beos/PlaybackNode.cc
Normal file
538
portaudio-v19/pa_beos/PlaybackNode.cc
Normal file
@ -0,0 +1,538 @@
|
|||||||
|
/*
|
||||||
|
* $Id: PlaybackNode.cc,v 1.1.1.1 2002/01/22 00:52:07 phil Exp $
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* Latest Version at: http://www.portaudio.com
|
||||||
|
* BeOS Media Kit Implementation by Joshua Haberman
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001 Joshua Haberman <joshua@haberman.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* Significant portions of this file are based on sample code from Be. The
|
||||||
|
* Be Sample Code Licence follows:
|
||||||
|
*
|
||||||
|
* Copyright 1991-1999, Be Incorporated.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions, and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions, and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||||
|
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <be/media/BufferGroup.h>
|
||||||
|
#include <be/media/Buffer.h>
|
||||||
|
#include <be/media/TimeSource.h>
|
||||||
|
|
||||||
|
#include "PlaybackNode.h"
|
||||||
|
|
||||||
|
#define PRINT(x) { printf x; fflush(stdout); }
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DBUG(x) PRINT(x)
|
||||||
|
#else
|
||||||
|
#define DBUG(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
PaPlaybackNode::PaPlaybackNode(uint32 channels, float frame_rate, uint32 frames_per_buffer,
|
||||||
|
PortAudioCallback* callback, void *user_data) :
|
||||||
|
BMediaNode("PortAudio input node"),
|
||||||
|
BBufferProducer(B_MEDIA_RAW_AUDIO),
|
||||||
|
BMediaEventLooper(),
|
||||||
|
mAborted(false),
|
||||||
|
mRunning(false),
|
||||||
|
mBufferGroup(NULL),
|
||||||
|
mDownstreamLatency(0),
|
||||||
|
mStartTime(0),
|
||||||
|
mCallback(callback),
|
||||||
|
mUserData(user_data),
|
||||||
|
mFramesPerBuffer(frames_per_buffer)
|
||||||
|
{
|
||||||
|
DBUG(("Constructor called.\n"));
|
||||||
|
|
||||||
|
mPreferredFormat.type = B_MEDIA_RAW_AUDIO;
|
||||||
|
mPreferredFormat.u.raw_audio.channel_count = channels;
|
||||||
|
mPreferredFormat.u.raw_audio.frame_rate = frame_rate;
|
||||||
|
mPreferredFormat.u.raw_audio.byte_order =
|
||||||
|
(B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
|
||||||
|
mPreferredFormat.u.raw_audio.buffer_size =
|
||||||
|
media_raw_audio_format::wildcard.buffer_size;
|
||||||
|
|
||||||
|
mOutput.destination = media_destination::null;
|
||||||
|
mOutput.format = mPreferredFormat;
|
||||||
|
|
||||||
|
/* The amount of time it takes for this node to produce a buffer when
|
||||||
|
* asked. Essentially, it is how long the user's callback takes to run.
|
||||||
|
* We set this to be the length of the sound data each buffer of the
|
||||||
|
* requested size can hold. */
|
||||||
|
//mInternalLatency = (bigtime_t)(1000000 * frames_per_buffer / frame_rate);
|
||||||
|
|
||||||
|
/* ACK! it seems that the mixer (at least on my machine) demands that IT
|
||||||
|
* specify the buffer size, so for now I'll just make a generic guess here */
|
||||||
|
mInternalLatency = 1000000 / 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PaPlaybackNode::~PaPlaybackNode()
|
||||||
|
{
|
||||||
|
DBUG(("Destructor called.\n"));
|
||||||
|
Quit(); /* Stop the BMediaEventLooper thread */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
*
|
||||||
|
* Local methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool PaPlaybackNode::IsRunning()
|
||||||
|
{
|
||||||
|
return mRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PaTimestamp PaPlaybackNode::GetStreamTime()
|
||||||
|
{
|
||||||
|
BTimeSource *timeSource = TimeSource();
|
||||||
|
PaTimestamp time = (timeSource->Now() - mStartTime) *
|
||||||
|
mPreferredFormat.u.raw_audio.frame_rate / 1000000;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaPlaybackNode::SetSampleFormat(PaSampleFormat inFormat,
|
||||||
|
PaSampleFormat outFormat)
|
||||||
|
{
|
||||||
|
uint32 beOutFormat;
|
||||||
|
|
||||||
|
switch(outFormat)
|
||||||
|
{
|
||||||
|
case paFloat32:
|
||||||
|
beOutFormat = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
|
mOutputSampleWidth = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt16:
|
||||||
|
beOutFormat = media_raw_audio_format::B_AUDIO_SHORT;
|
||||||
|
mOutputSampleWidth = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt32:
|
||||||
|
beOutFormat = media_raw_audio_format::B_AUDIO_INT;
|
||||||
|
mOutputSampleWidth = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt8:
|
||||||
|
beOutFormat = media_raw_audio_format::B_AUDIO_CHAR;
|
||||||
|
mOutputSampleWidth = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paUInt8:
|
||||||
|
beOutFormat = media_raw_audio_format::B_AUDIO_UCHAR;
|
||||||
|
mOutputSampleWidth = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt24:
|
||||||
|
case paPackedInt24:
|
||||||
|
case paCustomFormat:
|
||||||
|
DBUG(("Unsupported output format: %x\n", outFormat));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DBUG(("Unknown output format: %x\n", outFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreferredFormat.u.raw_audio.format = beOutFormat;
|
||||||
|
mFramesPerBuffer * mPreferredFormat.u.raw_audio.channel_count * mOutputSampleWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBuffer *PaPlaybackNode::FillNextBuffer(bigtime_t time)
|
||||||
|
{
|
||||||
|
/* Get a buffer from the buffer group */
|
||||||
|
BBuffer *buf = mBufferGroup->RequestBuffer(
|
||||||
|
mOutput.format.u.raw_audio.buffer_size, BufferDuration());
|
||||||
|
unsigned long frames = mOutput.format.u.raw_audio.buffer_size /
|
||||||
|
mOutputSampleWidth / mOutput.format.u.raw_audio.channel_count;
|
||||||
|
bigtime_t start_time;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if( !buf )
|
||||||
|
{
|
||||||
|
DBUG(("Unable to allocate a buffer\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_time = mStartTime +
|
||||||
|
(bigtime_t)((double)mSamplesSent /
|
||||||
|
(double)mOutput.format.u.raw_audio.frame_rate /
|
||||||
|
(double)mOutput.format.u.raw_audio.channel_count *
|
||||||
|
1000000.0);
|
||||||
|
|
||||||
|
/* Now call the user callback to get the data */
|
||||||
|
ret = mCallback(NULL, /* Input buffer */
|
||||||
|
buf->Data(), /* Output buffer */
|
||||||
|
frames, /* Frames per buffer */
|
||||||
|
mSamplesSent / mOutput.format.u.raw_audio.channel_count, /* timestamp */
|
||||||
|
mUserData);
|
||||||
|
|
||||||
|
if( ret )
|
||||||
|
mAborted = true;
|
||||||
|
|
||||||
|
media_header *hdr = buf->Header();
|
||||||
|
|
||||||
|
hdr->type = B_MEDIA_RAW_AUDIO;
|
||||||
|
hdr->size_used = mOutput.format.u.raw_audio.buffer_size;
|
||||||
|
hdr->time_source = TimeSource()->ID();
|
||||||
|
hdr->start_time = start_time;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
*
|
||||||
|
* BMediaNode methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
BMediaAddOn *PaPlaybackNode::AddOn( int32 * ) const
|
||||||
|
{
|
||||||
|
DBUG(("AddOn() called.\n"));
|
||||||
|
return NULL; /* we don't provide service to outside applications */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::HandleMessage( int32 message, const void *data,
|
||||||
|
size_t size )
|
||||||
|
{
|
||||||
|
DBUG(("HandleMessage() called.\n"));
|
||||||
|
return B_ERROR; /* we don't define any custom messages */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
*
|
||||||
|
* BMediaEventLooper methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void PaPlaybackNode::NodeRegistered()
|
||||||
|
{
|
||||||
|
DBUG(("NodeRegistered() called.\n"));
|
||||||
|
|
||||||
|
/* Start the BMediaEventLooper thread */
|
||||||
|
SetPriority(B_REAL_TIME_PRIORITY);
|
||||||
|
Run();
|
||||||
|
|
||||||
|
/* set up as much information about our output as we can */
|
||||||
|
mOutput.source.port = ControlPort();
|
||||||
|
mOutput.source.id = 0;
|
||||||
|
mOutput.node = Node();
|
||||||
|
::strcpy(mOutput.name, "PortAudio Playback");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaPlaybackNode::HandleEvent( const media_timed_event *event,
|
||||||
|
bigtime_t lateness, bool realTimeEvent )
|
||||||
|
{
|
||||||
|
// DBUG(("HandleEvent() called.\n"));
|
||||||
|
status_t err;
|
||||||
|
|
||||||
|
switch(event->type)
|
||||||
|
{
|
||||||
|
case BTimedEventQueue::B_START:
|
||||||
|
DBUG((" Handling a B_START event\n"));
|
||||||
|
if( RunState() != B_STARTED )
|
||||||
|
{
|
||||||
|
mStartTime = event->event_time + EventLatency();
|
||||||
|
mSamplesSent = 0;
|
||||||
|
mAborted = false;
|
||||||
|
mRunning = true;
|
||||||
|
media_timed_event firstEvent( mStartTime,
|
||||||
|
BTimedEventQueue::B_HANDLE_BUFFER );
|
||||||
|
EventQueue()->AddEvent( firstEvent );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BTimedEventQueue::B_STOP:
|
||||||
|
DBUG((" Handling a B_STOP event\n"));
|
||||||
|
mRunning = false;
|
||||||
|
EventQueue()->FlushEvents( 0, BTimedEventQueue::B_ALWAYS, true,
|
||||||
|
BTimedEventQueue::B_HANDLE_BUFFER );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BTimedEventQueue::B_HANDLE_BUFFER:
|
||||||
|
//DBUG((" Handling a B_HANDLE_BUFFER event\n"));
|
||||||
|
|
||||||
|
/* make sure we're started and connected */
|
||||||
|
if( RunState() != BMediaEventLooper::B_STARTED ||
|
||||||
|
mOutput.destination == media_destination::null )
|
||||||
|
break;
|
||||||
|
|
||||||
|
BBuffer *buffer = FillNextBuffer(event->event_time);
|
||||||
|
|
||||||
|
/* make sure we weren't aborted while this routine was running.
|
||||||
|
* this can happen in one of two ways: either the callback returned
|
||||||
|
* nonzero (in which case mAborted is set in FillNextBuffer() ) or
|
||||||
|
* the client called AbortStream */
|
||||||
|
if( mAborted )
|
||||||
|
{
|
||||||
|
if( buffer )
|
||||||
|
buffer->Recycle();
|
||||||
|
Stop(0, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( buffer )
|
||||||
|
{
|
||||||
|
err = SendBuffer(buffer, mOutput.destination);
|
||||||
|
if( err != B_OK )
|
||||||
|
buffer->Recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
mSamplesSent += mOutput.format.u.raw_audio.buffer_size / mOutputSampleWidth;
|
||||||
|
|
||||||
|
/* Now schedule the next buffer event, so we can send another
|
||||||
|
* buffer when this one runs out. We calculate when it should
|
||||||
|
* happen by calculating when the data we just sent will finish
|
||||||
|
* playing.
|
||||||
|
*
|
||||||
|
* NOTE, however, that the event will actually get generated
|
||||||
|
* earlier than we specify, to account for the latency it will
|
||||||
|
* take to produce the buffer. It uses the latency value we
|
||||||
|
* specified in SetEventLatency() to determine just how early
|
||||||
|
* to generate it. */
|
||||||
|
|
||||||
|
/* totalPerformanceTime includes the time represented by the buffer
|
||||||
|
* we just sent */
|
||||||
|
bigtime_t totalPerformanceTime = (bigtime_t)((double)mSamplesSent /
|
||||||
|
(double)mOutput.format.u.raw_audio.channel_count /
|
||||||
|
(double)mOutput.format.u.raw_audio.frame_rate * 1000000.0);
|
||||||
|
|
||||||
|
bigtime_t nextEventTime = mStartTime + totalPerformanceTime;
|
||||||
|
|
||||||
|
media_timed_event nextBufferEvent(nextEventTime,
|
||||||
|
BTimedEventQueue::B_HANDLE_BUFFER);
|
||||||
|
EventQueue()->AddEvent(nextBufferEvent);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
*
|
||||||
|
* BBufferProducer methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::FormatSuggestionRequested( media_type type,
|
||||||
|
int32 /*quality*/, media_format* format )
|
||||||
|
{
|
||||||
|
/* the caller wants to know this node's preferred format and provides
|
||||||
|
* a suggestion, asking if we support it */
|
||||||
|
DBUG(("FormatSuggestionRequested() called.\n"));
|
||||||
|
|
||||||
|
if(!format)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
*format = mPreferredFormat;
|
||||||
|
|
||||||
|
/* we only support raw audio (a wildcard is okay too) */
|
||||||
|
if ( type == B_MEDIA_UNKNOWN_TYPE || type == B_MEDIA_RAW_AUDIO )
|
||||||
|
return B_OK;
|
||||||
|
else
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::FormatProposal( const media_source& output,
|
||||||
|
media_format* format )
|
||||||
|
{
|
||||||
|
/* This is similar to FormatSuggestionRequested(), but it is actually part
|
||||||
|
* of the negotiation process. We're given the opportunity to specify any
|
||||||
|
* properties that are wildcards (ie. properties that the other node doesn't
|
||||||
|
* care one way or another about) */
|
||||||
|
DBUG(("FormatProposal() called.\n"));
|
||||||
|
|
||||||
|
/* Make sure this proposal really applies to our output */
|
||||||
|
if( output != mOutput.source )
|
||||||
|
return B_MEDIA_BAD_SOURCE;
|
||||||
|
|
||||||
|
/* We return two things: whether we support the proposed format, and our own
|
||||||
|
* preferred format */
|
||||||
|
*format = mPreferredFormat;
|
||||||
|
|
||||||
|
if( format->type == B_MEDIA_UNKNOWN_TYPE || format->type == B_MEDIA_RAW_AUDIO )
|
||||||
|
return B_OK;
|
||||||
|
else
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::FormatChangeRequested( const media_source& source,
|
||||||
|
const media_destination& destination, media_format* io_format, int32* )
|
||||||
|
{
|
||||||
|
/* we refuse to change formats, supporting only 1 */
|
||||||
|
DBUG(("FormatChangeRequested() called.\n"));
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::GetNextOutput( int32* cookie, media_output* out_output )
|
||||||
|
{
|
||||||
|
/* this is where we allow other to enumerate our outputs -- the cookie is
|
||||||
|
* an integer we can use to keep track of where we are in enumeration. */
|
||||||
|
DBUG(("GetNextOutput() called.\n"));
|
||||||
|
|
||||||
|
if( *cookie == 0 )
|
||||||
|
{
|
||||||
|
*out_output = mOutput;
|
||||||
|
*cookie = 1;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::DisposeOutputCookie( int32 cookie )
|
||||||
|
{
|
||||||
|
DBUG(("DisposeOutputCookie() called.\n"));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaPlaybackNode::LateNoticeReceived( const media_source& what,
|
||||||
|
bigtime_t how_much, bigtime_t performance_time )
|
||||||
|
{
|
||||||
|
/* This function is called as notification that a buffer we sent wasn't
|
||||||
|
* received by the time we stamped it with -- it got there late. Basically,
|
||||||
|
* it means we underestimated our own latency, so we should increase it */
|
||||||
|
DBUG(("LateNoticeReceived() called.\n"));
|
||||||
|
|
||||||
|
if( what != mOutput.source )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( RunMode() == B_INCREASE_LATENCY )
|
||||||
|
{
|
||||||
|
mInternalLatency += how_much;
|
||||||
|
SetEventLatency( mDownstreamLatency + mInternalLatency );
|
||||||
|
DBUG(("Increasing latency to %Ld\n", mDownstreamLatency + mInternalLatency));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DBUG(("I don't know what to do with this notice!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaPlaybackNode::EnableOutput( const media_source& what, bool enabled,
|
||||||
|
int32* )
|
||||||
|
{
|
||||||
|
DBUG(("EnableOutput() called.\n"));
|
||||||
|
/* stub -- we don't support this yet */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PaPlaybackNode::PrepareToConnect( const media_source& what,
|
||||||
|
const media_destination& where, media_format* format,
|
||||||
|
media_source* out_source, char* out_name )
|
||||||
|
{
|
||||||
|
/* the final stage of format negotiations. here we _must_ make specific any
|
||||||
|
* remaining wildcards */
|
||||||
|
DBUG(("PrepareToConnect() called.\n"));
|
||||||
|
|
||||||
|
/* make sure this really refers to our source */
|
||||||
|
if( what != mOutput.source )
|
||||||
|
return B_MEDIA_BAD_SOURCE;
|
||||||
|
|
||||||
|
/* make sure we're not already connected */
|
||||||
|
if( mOutput.destination != media_destination::null )
|
||||||
|
return B_MEDIA_ALREADY_CONNECTED;
|
||||||
|
|
||||||
|
if( format->type != B_MEDIA_RAW_AUDIO )
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
|
||||||
|
if( format->u.raw_audio.format != mPreferredFormat.u.raw_audio.format )
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
|
||||||
|
if( format->u.raw_audio.buffer_size ==
|
||||||
|
media_raw_audio_format::wildcard.buffer_size )
|
||||||
|
{
|
||||||
|
DBUG(("We were left to decide buffer size: choosing 2048"));
|
||||||
|
format->u.raw_audio.buffer_size = 2048;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DBUG(("Using consumer specified buffer size of %lu.\n",
|
||||||
|
format->u.raw_audio.buffer_size));
|
||||||
|
|
||||||
|
/* Reserve the connection, return the information */
|
||||||
|
mOutput.destination = where;
|
||||||
|
mOutput.format = *format;
|
||||||
|
*out_source = mOutput.source;
|
||||||
|
strncpy( out_name, mOutput.name, B_MEDIA_NAME_LENGTH );
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaPlaybackNode::Connect(status_t error, const media_source& source,
|
||||||
|
const media_destination& destination, const media_format& format, char* io_name)
|
||||||
|
{
|
||||||
|
DBUG(("Connect() called.\n"));
|
||||||
|
|
||||||
108
portaudio-v19/pa_beos/PlaybackNode.h
Normal file
108
portaudio-v19/pa_beos/PlaybackNode.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* Latest Version at: http://www.portaudio.com
|
||||||
|
* BeOS Media Kit Implementation by Joshua Haberman
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001 Joshua Haberman <joshua@haberman.com>
|
||||||
|
*
|
||||||
|
* 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 <be/media/MediaRoster.h>
|
||||||
|
#include <be/media/MediaEventLooper.h>
|
||||||
|
#include <be/media/BufferProducer.h>
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
|
||||||
|
class PaPlaybackNode :
|
||||||
|
public BBufferProducer,
|
||||||
|
public BMediaEventLooper
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
PaPlaybackNode( uint32 channels, float frame_rate, uint32 frames_per_buffer,
|
||||||
|
PortAudioCallback *callback, void *user_data );
|
||||||
|
~PaPlaybackNode();
|
||||||
|
|
||||||
|
|
||||||
|
/* Local methods ******************************************/
|
||||||
|
|
||||||
|
BBuffer *FillNextBuffer(bigtime_t time);
|
||||||
|
void SetSampleFormat(PaSampleFormat inFormat, PaSampleFormat outFormat);
|
||||||
|
bool IsRunning();
|
||||||
|
PaTimestamp GetStreamTime();
|
||||||
|
|
||||||
|
/* BMediaNode methods *************************************/
|
||||||
|
|
||||||
|
BMediaAddOn* AddOn( int32 * ) const;
|
||||||
|
status_t HandleMessage( int32 message, const void *data, size_t size );
|
||||||
|
|
||||||
|
/* BMediaEventLooper methods ******************************/
|
||||||
|
|
||||||
|
void HandleEvent( const media_timed_event *event, bigtime_t lateness,
|
||||||
|
bool realTimeEvent );
|
||||||
|
void NodeRegistered();
|
||||||
|
|
||||||
|
/* BBufferProducer methods ********************************/
|
||||||
|
|
||||||
|
status_t FormatSuggestionRequested( media_type type, int32 quality,
|
||||||
|
media_format* format );
|
||||||
|
status_t FormatProposal( const media_source& output, media_format* format );
|
||||||
|
status_t FormatChangeRequested( const media_source& source,
|
||||||
|
const media_destination& destination, media_format* io_format, int32* );
|
||||||
|
|
||||||
|
status_t GetNextOutput( int32* cookie, media_output* out_output );
|
||||||
|
status_t DisposeOutputCookie( int32 cookie );
|
||||||
|
|
||||||
|
void LateNoticeReceived( const media_source& what, bigtime_t how_much,
|
||||||
|
bigtime_t performance_time );
|
||||||
|
void EnableOutput( const media_source& what, bool enabled, int32* _deprecated_ );
|
||||||
|
|
||||||
|
status_t PrepareToConnect( const media_source& what,
|
||||||
|
const media_destination& where, media_format* format,
|
||||||
|
media_source* out_source, char* out_name );
|
||||||
|
void Connect(status_t error, const media_source& source,
|
||||||
|
const media_destination& destination, const media_format& format,
|
||||||
|
char* io_name);
|
||||||
|
void Disconnect(const media_source& what, const media_destination& where);
|
||||||
|
|
||||||
|
status_t SetBufferGroup(const media_source& for_source, BBufferGroup* newGroup);
|
||||||
|
|
||||||
|
bool mAborted;
|
||||||
|
|
||||||
|
private:
|
||||||
|
media_output mOutput;
|
||||||
|
media_format mPreferredFormat;
|
||||||
|
uint32 mOutputSampleWidth, mFramesPerBuffer;
|
||||||
|
BBufferGroup *mBufferGroup;
|
||||||
|
bigtime_t mDownstreamLatency, mInternalLatency, mStartTime;
|
||||||
|
uint64 mSamplesSent;
|
||||||
|
PortAudioCallback *mCallback;
|
||||||
|
void *mUserData;
|
||||||
|
bool mRunning;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
441
portaudio-v19/pa_beos/pa_beos_mk.cc
Normal file
441
portaudio-v19/pa_beos/pa_beos_mk.cc
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/*
|
||||||
|
* $Id: pa_beos_mk.cc,v 1.1.1.1 2002/01/22 00:52:09 phil Exp $
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* Latest Version at: http://www.portaudio.com
|
||||||
|
* BeOS Media Kit Implementation by Joshua Haberman
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001 Joshua Haberman <joshua@haberman.com>
|
||||||
|
*
|
||||||
|
* 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 <be/app/Application.h>
|
||||||
|
#include <be/kernel/OS.h>
|
||||||
|
#include <be/media/RealtimeAlloc.h>
|
||||||
|
#include <be/media/MediaRoster.h>
|
||||||
|
#include <be/media/TimeSource.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
#include "pa_host.h"
|
||||||
|
|
||||||
|
#include "PlaybackNode.h"
|
||||||
|
|
||||||
|
#define PRINT(x) { printf x; fflush(stdout); }
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DBUG(x) PRINT(x)
|
||||||
|
#else
|
||||||
|
#define DBUG(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct PaHostSoundControl
|
||||||
|
{
|
||||||
|
/* These members are common to all modes of operation */
|
||||||
|
media_node pahsc_TimeSource; /* the sound card's DAC. */
|
||||||
|
media_format pahsc_Format;
|
||||||
|
|
||||||
|
/* These methods are specific to playing mode */
|
||||||
|
media_node pahsc_OutputNode; /* output to the mixer */
|
||||||
|
media_node pahsc_InputNode; /* reads data from user callback -- PA specific */
|
||||||
|
|
||||||
|
media_input pahsc_MixerInput; /* input jack on the soundcard's mixer. */
|
||||||
|
media_output pahsc_PaOutput; /* output jack from the PA node */
|
||||||
|
|
||||||
|
PaPlaybackNode *pahsc_InputNodeInstance;
|
||||||
|
|
||||||
|
}
|
||||||
|
PaHostSoundControl;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaDeviceID Pa_GetDefaultOutputDeviceID( void )
|
||||||
|
{
|
||||||
|
/* stub */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaDeviceID Pa_GetDefaultInputDeviceID( void )
|
||||||
|
{
|
||||||
|
/* stub */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id )
|
||||||
|
{
|
||||||
|
/* stub */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
int Pa_CountDevices()
|
||||||
|
{
|
||||||
|
/* stub */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_Init( void )
|
||||||
|
{
|
||||||
|
/* we have to create this in order to use BMediaRoster. I hope it doesn't
|
||||||
|
* cause problems */
|
||||||
|
be_app = new BApplication("application/x-vnd.portaudio-app");
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaError PaHost_Term( void )
|
||||||
|
{
|
||||||
|
delete be_app;
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_StreamActive( internalPortAudioStream *past )
|
||||||
|
{
|
||||||
|
PaHostSoundControl *pahsc = (PaHostSoundControl *)past->past_DeviceData;
|
||||||
|
DBUG(("IsRunning returning: %s\n",
|
||||||
|
pahsc->pahsc_InputNodeInstance->IsRunning() ? "true" : "false"));
|
||||||
|
|
||||||
|
return (PaError)pahsc->pahsc_InputNodeInstance->IsRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
PaError PaHost_StartOutput( internalPortAudioStream *past )
|
||||||
|
{
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_StartInput( internalPortAudioStream *past )
|
||||||
|
{
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_StopInput( internalPortAudioStream *past, int abort )
|
||||||
|
{
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_StopOutput( internalPortAudioStream *past, int abort )
|
||||||
|
{
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_StartEngine( internalPortAudioStream *past )
|
||||||
|
{
|
||||||
|
bigtime_t very_soon, start_latency;
|
||||||
|
status_t err;
|
||||||
|
BMediaRoster *roster = BMediaRoster::Roster(&err);
|
||||||
|
PaHostSoundControl *pahsc = (PaHostSoundControl *)past->past_DeviceData;
|
||||||
|
|
||||||
|
/* for some reason, err indicates an error (though nothing it wrong)
|
||||||
|
* when the DBUG macro in pa_lib.c is enabled. It's reproducably
|
||||||
|
* linked. Weird. */
|
||||||
|
if( !roster /* || err != B_OK */ )
|
||||||
|
{
|
||||||
|
DBUG(("No media server! err=%d, roster=%x\n", err, roster));
|
||||||
|
return paHostError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tell the node when to start -- since there aren't any other nodes
|
||||||
|
* starting that we have to wait for, just tell it to start now
|
||||||
|
*/
|
||||||
|
|
||||||
|
BTimeSource *timeSource = roster->MakeTimeSourceFor(pahsc->pahsc_TimeSource);
|
||||||
|
very_soon = timeSource->PerformanceTimeFor( BTimeSource::RealTime() );
|
||||||
|
timeSource->Release();
|
||||||
|
|
||||||
|
/* Add the latency of starting the network of nodes */
|
||||||
|
err = roster->GetStartLatencyFor( pahsc->pahsc_TimeSource, &start_latency );
|
||||||
|
very_soon += start_latency;
|
||||||
|
|
||||||
|
err = roster->StartNode( pahsc->pahsc_InputNode, very_soon );
|
||||||
|
/* No need to start the mixer -- it's always running */
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_StopEngine( internalPortAudioStream *past, int abort )
|
||||||
|
{
|
||||||
|
PaHostSoundControl *pahsc = (PaHostSoundControl *)past->past_DeviceData;
|
||||||
|
BMediaRoster *roster = BMediaRoster::Roster();
|
||||||
|
|
||||||
|
if( !roster )
|
||||||
|
{
|
||||||
|
DBUG(("No media roster!\n"));
|
||||||
|
return paHostError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !pahsc )
|
||||||
|
return paHostError;
|
||||||
|
|
||||||
|
/* this crashes, and I don't know why yet */
|
||||||
|
// if( abort )
|
||||||
|
// pahsc->pahsc_InputNodeInstance->mAborted = true;
|
||||||
|
|
||||||
|
roster->StopNode(pahsc->pahsc_InputNode, 0, /* immediate = */ true);
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_OpenStream( internalPortAudioStream *past )
|
||||||
|
{
|
||||||
|
status_t err;
|
||||||
|
BMediaRoster *roster = BMediaRoster::Roster(&err);
|
||||||
|
PaHostSoundControl *pahsc;
|
||||||
|
|
||||||
|
/* Allocate and initialize host data. */
|
||||||
|
pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl));
|
||||||
|
if( pahsc == NULL )
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memset( pahsc, 0, sizeof(PaHostSoundControl) );
|
||||||
|
past->past_DeviceData = (void *) pahsc;
|
||||||
|
|
||||||
|
if( !roster /* || err != B_OK */ )
|
||||||
|
{
|
||||||
|
/* no media server! */
|
||||||
|
DBUG(("No media server.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( past->past_NumInputChannels > 0 && past->past_NumOutputChannels > 0 )
|
||||||
|
{
|
||||||
|
/* filter -- not implemented yet */
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if ( past->past_NumInputChannels > 0 )
|
||||||
|
{
|
||||||
|
/* recorder -- not implemented yet */
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* player ****************************************************************/
|
||||||
|
|
||||||
|
status_t err;
|
||||||
|
int32 num;
|
||||||
|
|
||||||
|
/* First we need to create the three components (like components in a stereo
|
||||||
|
* system). The mixer component is our interface to the sound card, data
|
||||||
|
* we write there will get played. The BePA_InputNode component is the node
|
||||||
|
* which represents communication with the PA client (it is what calls the
|
||||||
|
* client's callbacks). The time source component is the sound card's DAC,
|
||||||
|
* which allows us to slave the other components to it instead of the system
|
||||||
|
* clock. */
|
||||||
|
err = roster->GetAudioMixer( &pahsc->pahsc_OutputNode );
|
||||||
|
if( err != B_OK )
|
||||||
|
{
|
||||||
|
DBUG(("Couldn't get default mixer.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = roster->GetTimeSource( &pahsc->pahsc_TimeSource );
|
||||||
|
if( err != B_OK )
|
||||||
|
{
|
||||||
|
DBUG(("Couldn't get time source.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pahsc->pahsc_InputNodeInstance = new PaPlaybackNode(2, 44100,
|
||||||
|
past->past_FramesPerUserBuffer, past->past_Callback, past->past_UserData );
|
||||||
|
pahsc->pahsc_InputNodeInstance->SetSampleFormat(0,
|
||||||
|
past->past_OutputSampleFormat);
|
||||||
|
err = roster->RegisterNode( pahsc->pahsc_InputNodeInstance );
|
||||||
|
if( err != B_OK )
|
||||||
|
{
|
||||||
|
DBUG(("Unable to register node.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
roster->GetNodeFor( pahsc->pahsc_InputNodeInstance->Node().node,
|
||||||
|
&pahsc->pahsc_InputNode );
|
||||||
|
if( err != B_OK )
|
||||||
|
{
|
||||||
|
DBUG(("Unable to get input node.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we have three components (nodes) sitting next to each other. The
|
||||||
|
* next step is to look at them and find their inputs and outputs so we can
|
||||||
|
* wire them together. */
|
||||||
|
err = roster->GetFreeInputsFor( pahsc->pahsc_OutputNode,
|
||||||
|
&pahsc->pahsc_MixerInput, 1, &num, B_MEDIA_RAW_AUDIO );
|
||||||
|
if( err != B_OK || num < 1 )
|
||||||
|
{
|
||||||
|
DBUG(("Couldn't get the mixer input.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = roster->GetFreeOutputsFor( pahsc->pahsc_InputNode,
|
||||||
|
&pahsc->pahsc_PaOutput, 1, &num, B_MEDIA_RAW_AUDIO );
|
||||||
|
if( err != B_OK || num < 1 )
|
||||||
|
{
|
||||||
|
DBUG(("Couldn't get PortAudio output.\n"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* We've found the input and output -- the final step is to run a wire
|
||||||
|
* between them so they are connected. */
|
||||||
|
|
||||||
|
/* try to make the mixer input adapt to what PA sends it */
|
||||||
|
pahsc->pahsc_Format = pahsc->pahsc_PaOutput.format;
|
||||||
|
roster->Connect( pahsc->pahsc_PaOutput.source,
|
||||||
|
pahsc->pahsc_MixerInput.destination, &pahsc->pahsc_Format,
|
||||||
|
&pahsc->pahsc_PaOutput, &pahsc->pahsc_MixerInput );
|
||||||
|
|
||||||
|
|
||||||
|
/* Actually, there's one final step -- tell them all to sync to the
|
||||||
|
* sound card's DAC */
|
||||||
|
roster->SetTimeSourceFor( pahsc->pahsc_InputNode.node,
|
||||||
|
pahsc->pahsc_TimeSource.node );
|
||||||
|
roster->SetTimeSourceFor( pahsc->pahsc_OutputNode.node,
|
||||||
|
pahsc->pahsc_TimeSource.node );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
|
||||||
|
error:
|
||||||
|
PaHost_CloseStream( past );
|
||||||
|
return paHostError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaError PaHost_CloseStream( internalPortAudioStream *past )
|
||||||
|
{
|
||||||
|
PaHostSoundControl *pahsc = (PaHostSoundControl *)past->past_DeviceData;
|
||||||
|
status_t err;
|
||||||
|
BMediaRoster *roster = BMediaRoster::Roster(&err);
|
||||||
|
|
||||||
|
if( !roster )
|
||||||
|
{
|
||||||
|
DBUG(("Couldn't get media roster\n"));
|
||||||
|
return paHostError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !pahsc )
|
||||||
|
return paHostError;
|
||||||
|
|
||||||
|
/* Disconnect all the connections we made when opening the stream */
|
||||||
|
|
||||||
|
roster->Disconnect(pahsc->pahsc_InputNode.node, pahsc->pahsc_PaOutput.source,
|
||||||
|
pahsc->pahsc_OutputNode.node, pahsc->pahsc_MixerInput.destination);
|
||||||
|
|
||||||
|
DBUG(("Calling ReleaseNode()"));
|
||||||
|
roster->ReleaseNode(pahsc->pahsc_InputNode);
|
||||||
|
|
||||||
|
/* deleting the node shouldn't be necessary -- it is reference counted, and will
|
||||||
|
* delete itself when its references drop to zero. the call to ReleaseNode()
|
||||||
|
* above should decrease its reference count */
|
||||||
|
pahsc->pahsc_InputNodeInstance = NULL;
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
PaTimestamp Pa_StreamTime( PortAudioStream *stream )
|
||||||
|
{
|
||||||
|
internalPortAudioStream *past = (internalPortAudioStream *) stream;
|
||||||
|
PaHostSoundControl *pahsc = (PaHostSoundControl *)past->past_DeviceData;
|
||||||
|
|
||||||
|
return pahsc->pahsc_InputNodeInstance->GetStreamTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
void Pa_Sleep( long msec )
|
||||||
|
{
|
||||||
|
/* snooze() takes microseconds */
|
||||||
|
snooze( msec * 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Allocate memory that can be accessed in real-time.
|
||||||
|
* This may need to be held in physical memory so that it is not
|
||||||
|
* paged to virtual memory.
|
||||||
|
* This call MUST be balanced with a call to PaHost_FreeFastMemory().
|
||||||
|
* Memory will be set to zero.
|
||||||
|
*/
|
||||||
|
void *PaHost_AllocateFastMemory( long numBytes )
|
||||||
|
{
|
||||||
|
/* BeOS supports non-pagable memory through pools -- a pool is an area
|
||||||
|
* of physical memory that is locked. It would be best to pre-allocate
|
||||||
|
* that pool and then hand out memory from it, but we don't know in
|
||||||
|
* advance how much we'll need. So for now, we'll allocate a pool
|
||||||
|
* for every request we get, storing a pointer to the pool at the
|
||||||
|
* beginning of the allocated memory */
|
||||||
|
rtm_pool *pool;
|
||||||
|
void *addr;
|
||||||
|
long size = numBytes + sizeof(rtm_pool *);
|
||||||
|
static int counter = 0;
|
||||||
|
char pool_name[100];
|
||||||
|
|
||||||
|
/* Every pool needs a unique name. */
|
||||||
|
sprintf(pool_name, "PaPoolNumber%d", counter++);
|
||||||
|
|
||||||
|
if( rtm_create_pool( &pool, size, pool_name ) != B_OK )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
addr = rtm_alloc( pool, size );
|
||||||
|
if( addr == NULL )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset( addr, 0, numBytes );
|
||||||
|
*((rtm_pool **)addr) = pool; // store the pointer to the pool
|
||||||
|
addr = (rtm_pool **)addr + 1; // and return the next location in memory
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Free memory that could be accessed in real-time.
|
||||||
|
* This call MUST be balanced with a call to PaHost_AllocateFastMemory().
|
||||||
|
*/
|
||||||
|
void PaHost_FreeFastMemory( void *addr, long numBytes )
|
||||||
|
{
|
||||||
|
rtm_pool *pool;
|
||||||
|
|
||||||
|
if( addr == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
addr = (rtm_pool **)addr - 1;
|
||||||
|
pool = *((rtm_pool **)addr);
|
||||||
|
|
||||||
|
rtm_free( addr );
|
||||||
|
rtm_delete_pool( pool );
|
||||||
|
}
|
||||||
234
portaudio-v19/pa_common/pa_allocation.c
Normal file
234
portaudio-v19/pa_common/pa_allocation.c
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library allocation group implementation
|
||||||
|
* memory allocation group for tracking allocation groups
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
@brief Allocation Group implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pa_allocation.h"
|
||||||
|
#include "pa_util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Maintain 3 singly linked lists...
|
||||||
|
linkBlocks: the buffers used to allocate the links
|
||||||
|
spareLinks: links available for use in the allocations list
|
||||||
|
allocations: the buffers currently allocated using PaUtil_ContextAllocateMemory()
|
||||||
|
|
||||||
|
Link block size is doubled every time new links are allocated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define PA_INITIAL_LINK_COUNT_ 16
|
||||||
|
|
||||||
|
struct PaUtilAllocationGroupLink
|
||||||
|
{
|
||||||
|
struct PaUtilAllocationGroupLink *next;
|
||||||
|
void *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Allocate a block of links. The first link will have it's buffer member
|
||||||
|
pointing to the block, and it's next member set to <nextBlock>. The remaining
|
||||||
|
links will have NULL buffer members, and each link will point to
|
||||||
|
the next link except the last, which will point to <nextSpare>
|
||||||
|
*/
|
||||||
|
static struct PaUtilAllocationGroupLink *AllocateLinks( long count,
|
||||||
|
struct PaUtilAllocationGroupLink *nextBlock,
|
||||||
|
struct PaUtilAllocationGroupLink *nextSpare )
|
||||||
|
{
|
||||||
|
struct PaUtilAllocationGroupLink *result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory(
|
||||||
|
sizeof(struct PaUtilAllocationGroupLink) * count );
|
||||||
|
if( result )
|
||||||
|
{
|
||||||
|
/* the block link */
|
||||||
|
result[0].buffer = result;
|
||||||
|
result[0].next = nextBlock;
|
||||||
|
|
||||||
|
/* the spare links */
|
||||||
|
for( i=1; i<count; ++i )
|
||||||
|
{
|
||||||
|
result[i].buffer = 0;
|
||||||
|
result[i].next = &result[i+1];
|
||||||
|
}
|
||||||
|
result[count-1].next = nextSpare;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void )
|
||||||
|
{
|
||||||
|
PaUtilAllocationGroup* result = 0;
|
||||||
|
struct PaUtilAllocationGroupLink *links;
|
||||||
|
|
||||||
|
|
||||||
|
links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 );
|
||||||
|
if( links != 0 )
|
||||||
|
{
|
||||||
|
result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) );
|
||||||
|
if( result )
|
||||||
|
{
|
||||||
|
result->linkCount = PA_INITIAL_LINK_COUNT_;
|
||||||
|
result->linkBlocks = &links[0];
|
||||||
|
result->spareLinks = &links[1];
|
||||||
|
result->allocations = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PaUtil_FreeMemory( links );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group )
|
||||||
|
{
|
||||||
|
struct PaUtilAllocationGroupLink *current = group->linkBlocks;
|
||||||
|
struct PaUtilAllocationGroupLink *next;
|
||||||
|
|
||||||
|
while( current )
|
||||||
|
{
|
||||||
|
next = current->next;
|
||||||
|
PaUtil_FreeMemory( current->buffer );
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_FreeMemory( group );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size )
|
||||||
|
{
|
||||||
|
struct PaUtilAllocationGroupLink *links, *link;
|
||||||
|
void *result = 0;
|
||||||
|
|
||||||
|
/* allocate more links if necessary */
|
||||||
|
if( !group->spareLinks )
|
||||||
|
{
|
||||||
|
/* double the link count on each block allocation */
|
||||||
|
links = AllocateLinks( group->linkCount, group->linkBlocks, group->spareLinks );
|
||||||
|
if( links )
|
||||||
|
{
|
||||||
|
group->linkCount += group->linkCount;
|
||||||
|
group->linkBlocks = &links[0];
|
||||||
|
group->spareLinks = &links[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( group->spareLinks )
|
||||||
|
{
|
||||||
|
result = PaUtil_AllocateMemory( size );
|
||||||
|
if( result )
|
||||||
|
{
|
||||||
|
link = group->spareLinks;
|
||||||
|
group->spareLinks = link->next;
|
||||||
|
|
||||||
|
link->buffer = result;
|
||||||
|
link->next = group->allocations;
|
||||||
|
|
||||||
|
group->allocations = link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer )
|
||||||
|
{
|
||||||
|
struct PaUtilAllocationGroupLink *current = group->allocations;
|
||||||
|
struct PaUtilAllocationGroupLink *previous = 0;
|
||||||
|
|
||||||
|
if( buffer == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* find the right link and remove it */
|
||||||
|
while( current )
|
||||||
|
{
|
||||||
|
if( current->buffer == buffer )
|
||||||
|
{
|
||||||
|
if( previous )
|
||||||
|
{
|
||||||
|
previous->next = current->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group->allocations = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->buffer = 0;
|
||||||
|
current->next = group->spareLinks;
|
||||||
|
group->spareLinks = current;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_FreeMemory( buffer ); /* free the memory whether we found it in the list or not */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group )
|
||||||
|
{
|
||||||
|
struct PaUtilAllocationGroupLink *current = group->allocations;
|
||||||
|
struct PaUtilAllocationGroupLink *previous = 0;
|
||||||
|
|
||||||
|
/* free all buffers in the allocations list */
|
||||||
|
while( current )
|
||||||
|
{
|
||||||
|
PaUtil_FreeMemory( current->buffer );
|
||||||
|
current->buffer = 0;
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* link the former allocations list onto the front of the spareLinks list */
|
||||||
|
if( previous )
|
||||||
|
{
|
||||||
|
previous->next = group->spareLinks;
|
||||||
|
group->spareLinks = group->allocations;
|
||||||
|
group->allocations = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
95
portaudio-v19/pa_common/pa_allocation.h
Normal file
95
portaudio-v19/pa_common/pa_allocation.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#ifndef PA_ALLOCATION_H
|
||||||
|
#define PA_ALLOCATION_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library allocation context header
|
||||||
|
* memory allocation context for tracking allocation groups
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
@brief Allocation Group prototypes. An Allocation Group makes it easy to
|
||||||
|
allocate multiple blocks of memory and free them all simultanously.
|
||||||
|
|
||||||
|
An allocation group is useful for keeping track of multiple blocks
|
||||||
|
of memory which are allocated at the same time (such as during initialization)
|
||||||
|
and need to be deallocated at the same time. The allocation group maintains
|
||||||
|
a list of allocated blocks, and can deallocate them all simultaneously which
|
||||||
|
can be usefull for cleaning up after a partially initialized object fails.
|
||||||
|
|
||||||
|
The allocation group implementation is built on top of the lower
|
||||||
|
level allocation functions defined in pa_util.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
long linkCount;
|
||||||
|
struct PaUtilAllocationGroupLink *linkBlocks;
|
||||||
|
struct PaUtilAllocationGroupLink *spareLinks;
|
||||||
|
struct PaUtilAllocationGroupLink *allocations;
|
||||||
|
}PaUtilAllocationGroup;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Create an allocation group.
|
||||||
|
*/
|
||||||
|
PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void );
|
||||||
|
|
||||||
|
/** Destroy an allocation group, but not the memory allocated through the group.
|
||||||
|
*/
|
||||||
|
void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group );
|
||||||
|
|
||||||
|
/** Allocate a block of memory though an allocation group.
|
||||||
|
*/
|
||||||
|
void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size );
|
||||||
|
|
||||||
|
/** Free a block of memory that was previously allocated though an allocation
|
||||||
|
group. Calling this function is a relatively time consuming operation.
|
||||||
|
Under normal circumstances clients should call PaUtil_FreeAllAllocations to
|
||||||
|
free all allocated blocks simultaneously.
|
||||||
|
@see PaUtil_FreeAllAllocations
|
||||||
|
*/
|
||||||
|
void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer );
|
||||||
|
|
||||||
|
/** Free all blocks of memory which have been allocated through the allocation
|
||||||
|
group. This function doesn't destroy the group itself.
|
||||||
|
*/
|
||||||
|
void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_ALLOCATION_H */
|
||||||
1926
portaudio-v19/pa_common/pa_converters.c
Normal file
1926
portaudio-v19/pa_common/pa_converters.c
Normal file
File diff suppressed because it is too large
Load Diff
254
portaudio-v19/pa_common/pa_converters.h
Normal file
254
portaudio-v19/pa_common/pa_converters.h
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
#ifndef PA_CONVERTERS_H
|
||||||
|
#define PA_CONVERTERS_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library sample conversion mechanism
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Conversion functions used to convert buffers of samples from one
|
||||||
|
format to another.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "portaudio.h" /* for PaSampleFormat */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
struct PaUtilTriangularDitherGenerator;
|
||||||
|
|
||||||
|
|
||||||
|
/** Choose an available sample format which is most appropriate for
|
||||||
|
representing the requested format. If the requested format is not available
|
||||||
|
higher quality formats are considered before lower quality formates.
|
||||||
|
@param availableFormats A variable containing the logical OR of all available
|
||||||
|
formats.
|
||||||
|
@param format The desired format.
|
||||||
|
@return The most appropriate available format for representing the requested
|
||||||
|
format.
|
||||||
|
*/
|
||||||
|
PaSampleFormat PaUtil_SelectClosestAvailableFormat(
|
||||||
|
PaSampleFormat availableFormats, PaSampleFormat format );
|
||||||
|
|
||||||
|
|
||||||
|
/* high level conversions functions for use by implementations */
|
||||||
|
|
||||||
|
|
||||||
|
/** The generic sample converter prototype. Sample converters convert count
|
||||||
|
samples from sourceBuffer to destinationBuffer. The actual type of the data
|
||||||
|
pointed to by these parameters varys for different converter functions.
|
||||||
|
@param destinationBuffer A pointer to the first sample of the destination.
|
||||||
|
@param destinationStride An offset between successive destination samples
|
||||||
|
expressed in samples (not bytes.) It may be negative.
|
||||||
|
@param sourceBuffer A pointer to the first sample of the source.
|
||||||
|
@param sourceStride An offset between successive source samples
|
||||||
|
expressed in samples (not bytes.) It may be negative.
|
||||||
|
@param count The number of samples to convert.
|
||||||
|
@param ditherState State information used to calculate dither. Converters
|
||||||
|
that do not perform dithering will ignore this parameter, in which case
|
||||||
|
NULL or invalid dither state may be passed.
|
||||||
|
*/
|
||||||
|
typedef void PaUtilConverter(
|
||||||
|
void *destinationBuffer, signed int destinationStride,
|
||||||
|
void *sourceBuffer, signed int sourceStride,
|
||||||
|
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator );
|
||||||
|
|
||||||
|
|
||||||
|
/** Find a sample converter function for the given source and destinations
|
||||||
|
formats and flags (clip and dither.)
|
||||||
|
@return
|
||||||
|
A pointer to a PaUtilConverter which will perform the requested
|
||||||
|
conversion, or NULL if the given format conversion is not supported.
|
||||||
|
For conversions where clipping or dithering is not necessary, the
|
||||||
|
clip and dither flags are ignored and a non-clipping or dithering
|
||||||
|
version is returned.
|
||||||
|
If the source and destination formats are the same, a function which
|
||||||
|
copies data of the appropriate size will be returned.
|
||||||
|
*/
|
||||||
|
PaUtilConverter* PaUtil_SelectConverter( PaSampleFormat sourceFormat,
|
||||||
|
PaSampleFormat destinationFormat, PaStreamFlags flags );
|
||||||
|
|
||||||
|
|
||||||
|
/** The generic buffer zeroer prototype. Buffer zeroers copy count zeros to
|
||||||
|
destinationBuffer. The actual type of the data pointed to varys for
|
||||||
|
different zeroer functions.
|
||||||
|
@param destinationBuffer A pointer to the first sample of the destination.
|
||||||
|
@param destinationStride An offset between successive destination samples
|
||||||
|
expressed in samples (not bytes.) It may be negative.
|
||||||
|
@param count The number of samples to zero.
|
||||||
|
*/
|
||||||
|
typedef void PaUtilZeroer(
|
||||||
|
void *destinationBuffer, signed int destinationStride, unsigned int count );
|
||||||
|
|
||||||
|
|
||||||
|
/** Find a buffer zeroer function for the given destination format.
|
||||||
|
@return
|
||||||
|
A pointer to a PaUtilZeroer which will perform the requested
|
||||||
|
zeroing.
|
||||||
|
*/
|
||||||
|
PaUtilZeroer* PaUtil_SelectZeroer( PaSampleFormat destinationFormat );
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/* low level functions and data structures which may be used for
|
||||||
|
substituting conversion functions */
|
||||||
|
|
||||||
|
|
||||||
|
/** The type used to store all sample conversion functions.
|
||||||
|
@see paConverters;
|
||||||
|
*/
|
||||||
|
typedef struct{
|
||||||
|
PaUtilConverter *Float32_To_Int32;
|
||||||
|
PaUtilConverter *Float32_To_Int32_Dither;
|
||||||
|
PaUtilConverter *Float32_To_Int32_Clip;
|
||||||
|
PaUtilConverter *Float32_To_Int32_DitherClip;
|
||||||
|
|
||||||
|
PaUtilConverter *Float32_To_Int24;
|
||||||
|
PaUtilConverter *Float32_To_Int24_Dither;
|
||||||
|
PaUtilConverter *Float32_To_Int24_Clip;
|
||||||
|
PaUtilConverter *Float32_To_Int24_DitherClip;
|
||||||
|
|
||||||
|
PaUtilConverter *Float32_To_Int16;
|
||||||
|
PaUtilConverter *Float32_To_Int16_Dither;
|
||||||
|
PaUtilConverter *Float32_To_Int16_Clip;
|
||||||
|
PaUtilConverter *Float32_To_Int16_DitherClip;
|
||||||
|
|
||||||
|
PaUtilConverter *Float32_To_Int8;
|
||||||
|
PaUtilConverter *Float32_To_Int8_Dither;
|
||||||
|
PaUtilConverter *Float32_To_Int8_Clip;
|
||||||
|
PaUtilConverter *Float32_To_Int8_DitherClip;
|
||||||
|
|
||||||
|
PaUtilConverter *Float32_To_UInt8;
|
||||||
|
PaUtilConverter *Float32_To_UInt8_Dither;
|
||||||
|
PaUtilConverter *Float32_To_UInt8_Clip;
|
||||||
|
PaUtilConverter *Float32_To_UInt8_DitherClip;
|
||||||
|
|
||||||
|
PaUtilConverter *Int32_To_Float32;
|
||||||
|
PaUtilConverter *Int32_To_Int24;
|
||||||
|
PaUtilConverter *Int32_To_Int24_Dither;
|
||||||
|
PaUtilConverter *Int32_To_Int16;
|
||||||
|
PaUtilConverter *Int32_To_Int16_Dither;
|
||||||
|
PaUtilConverter *Int32_To_Int8;
|
||||||
|
PaUtilConverter *Int32_To_Int8_Dither;
|
||||||
|
PaUtilConverter *Int32_To_UInt8;
|
||||||
|
PaUtilConverter *Int32_To_UInt8_Dither;
|
||||||
|
|
||||||
|
PaUtilConverter *Int24_To_Float32;
|
||||||
|
PaUtilConverter *Int24_To_Int32;
|
||||||
|
PaUtilConverter *Int24_To_Int16;
|
||||||
|
PaUtilConverter *Int24_To_Int16_Dither;
|
||||||
|
PaUtilConverter *Int24_To_Int8;
|
||||||
|
PaUtilConverter *Int24_To_Int8_Dither;
|
||||||
|
PaUtilConverter *Int24_To_UInt8;
|
||||||
|
PaUtilConverter *Int24_To_UInt8_Dither;
|
||||||
|
|
||||||
|
PaUtilConverter *Int16_To_Float32;
|
||||||
|
PaUtilConverter *Int16_To_Int32;
|
||||||
|
PaUtilConverter *Int16_To_Int24;
|
||||||
|
PaUtilConverter *Int16_To_Int8;
|
||||||
|
PaUtilConverter *Int16_To_Int8_Dither;
|
||||||
|
PaUtilConverter *Int16_To_UInt8;
|
||||||
|
PaUtilConverter *Int16_To_UInt8_Dither;
|
||||||
|
|
||||||
|
PaUtilConverter *Int8_To_Float32;
|
||||||
|
PaUtilConverter *Int8_To_Int32;
|
||||||
|
PaUtilConverter *Int8_To_Int24;
|
||||||
|
PaUtilConverter *Int8_To_Int16;
|
||||||
|
PaUtilConverter *Int8_To_UInt8;
|
||||||
|
|
||||||
|
PaUtilConverter *UInt8_To_Float32;
|
||||||
|
PaUtilConverter *UInt8_To_Int32;
|
||||||
|
PaUtilConverter *UInt8_To_Int24;
|
||||||
|
PaUtilConverter *UInt8_To_Int16;
|
||||||
|
PaUtilConverter *UInt8_To_Int8;
|
||||||
|
|
||||||
|
PaUtilConverter *Copy_8_To_8; /* copy without any conversion */
|
||||||
|
PaUtilConverter *Copy_16_To_16; /* copy without any conversion */
|
||||||
|
PaUtilConverter *Copy_24_To_24; /* copy without any conversion */
|
||||||
|
PaUtilConverter *Copy_32_To_32; /* copy without any conversion */
|
||||||
|
} PaUtilConverterTable;
|
||||||
|
|
||||||
|
|
||||||
|
/** A table of pointers to all required converter functions.
|
||||||
|
PaUtil_SelectConverter() uses this table to lookup the appropriate
|
||||||
|
conversion functions. The fields of this structure are initialized
|
||||||
|
with default conversion functions. Fields may be NULL, indicating that
|
||||||
|
no conversion function is available. User code may substitue optimised
|
||||||
|
conversion functions by assigning different function pointers to
|
||||||
|
these fields.
|
||||||
|
|
||||||
|
@note
|
||||||
|
If the PA_NO_STANDARD_CONVERTERS preprocessor variable is defined,
|
||||||
|
PortAudio's standard converters will not be compiled, and all fields
|
||||||
|
of this structure will be initialized to NULL. In such cases, users
|
||||||
|
should supply their own conversion functions if the require PortAudio
|
||||||
|
to open a stream that requires sample conversion.
|
||||||
|
|
||||||
|
@see PaUtilConverterTable, PaUtilConverter, PaUtil_SelectConverter
|
||||||
|
*/
|
||||||
|
extern PaUtilConverterTable paConverters;
|
||||||
|
|
||||||
|
|
||||||
|
/** The type used to store all buffer zeroing functions.
|
||||||
|
@see paZeroers;
|
||||||
|
*/
|
||||||
|
typedef struct{
|
||||||
|
PaUtilZeroer *ZeroU8; /* unsigned 8 bit, zero == 128 */
|
||||||
|
PaUtilZeroer *Zero8;
|
||||||
|
PaUtilZeroer *Zero16;
|
||||||
|
PaUtilZeroer *Zero24;
|
||||||
|
PaUtilZeroer *Zero32;
|
||||||
|
} PaUtilZeroerTable;
|
||||||
|
|
||||||
|
|
||||||
|
/** A table of pointers to all required zeroer functions.
|
||||||
|
PaUtil_SelectZeroer() uses this table to lookup the appropriate
|
||||||
|
conversion functions. The fields of this structure are initialized
|
||||||
|
with default conversion functions. User code may substitue optimised
|
||||||
|
conversion functions by assigning different function pointers to
|
||||||
|
these fields.
|
||||||
|
|
||||||
|
@note
|
||||||
|
If the PA_NO_STANDARD_ZEROERS preprocessor variable is defined,
|
||||||
|
PortAudio's standard zeroers will not be compiled, and all fields
|
||||||
|
of this structure will be initialized to NULL. In such cases, users
|
||||||
|
should supply their own zeroing functions for the sample sizes which
|
||||||
|
they intend to use.
|
||||||
|
|
||||||
|
@see PaUtilZeroerTable, PaUtilZeroer, PaUtil_SelectZeroer
|
||||||
|
*/
|
||||||
|
extern PaUtilZeroerTable paZeroers;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_CONVERTERS_H */
|
||||||
96
portaudio-v19/pa_common/pa_cpuload.c
Normal file
96
portaudio-v19/pa_common/pa_cpuload.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library CPU Load measurement functions
|
||||||
|
* Portable CPU load measurement facility.
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 2002 Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Functions to assist in measuring the CPU utilization of a callback
|
||||||
|
stream. Used to implement the Pa_GetStreamCpuLoad() function.
|
||||||
|
|
||||||
|
@todo Dynamically calculate the coefficients used to smooth the CPU Load
|
||||||
|
Measurements over time to provide a uniform characterisation of CPU Load
|
||||||
|
independent of rate at which PaUtil_BeginCpuLoadMeasurement /
|
||||||
|
PaUtil_EndCpuLoadMeasurement are called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pa_cpuload.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "pa_util.h" /* for PaUtil_GetTime() */
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate )
|
||||||
|
{
|
||||||
|
assert( sampleRate > 0 );
|
||||||
|
|
||||||
|
measurer->samplingPeriod = 1. / sampleRate;
|
||||||
|
measurer->averageLoad = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer )
|
||||||
|
{
|
||||||
|
measurer->averageLoad = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer )
|
||||||
|
{
|
||||||
|
measurer->measurementStartTime = PaUtil_GetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed )
|
||||||
|
{
|
||||||
|
double measurementEndTime, secondsFor100Percent, measuredLoad;
|
||||||
|
|
||||||
|
if( framesProcessed > 0 ){
|
||||||
|
measurementEndTime = PaUtil_GetTime();
|
||||||
|
|
||||||
|
assert( framesProcessed > 0 );
|
||||||
|
secondsFor100Percent = framesProcessed * measurer->samplingPeriod;
|
||||||
|
|
||||||
|
measuredLoad = (measurementEndTime - measurer->measurementStartTime) / secondsFor100Percent;
|
||||||
|
|
||||||
|
/* Low pass filter the calculated CPU load to reduce jitter using a simple IIR low pass filter. */
|
||||||
|
/** FIXME @todo these coefficients shouldn't be hardwired */
|
||||||
|
#define LOWPASS_COEFFICIENT_0 (0.9)
|
||||||
|
#define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0)
|
||||||
|
|
||||||
|
measurer->averageLoad = (LOWPASS_COEFFICIENT_0 * measurer->averageLoad) +
|
||||||
|
(LOWPASS_COEFFICIENT_1 * measuredLoad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer )
|
||||||
|
{
|
||||||
|
return measurer->averageLoad;
|
||||||
|
}
|
||||||
63
portaudio-v19/pa_common/pa_cpuload.h
Normal file
63
portaudio-v19/pa_common/pa_cpuload.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef PA_CPULOAD_H
|
||||||
|
#define PA_CPULOAD_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library CPU Load measurement functions
|
||||||
|
* Portable CPU load measurement facility.
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 2002 Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Functions to assist in measuring the CPU utilization of a callback
|
||||||
|
stream. Used to implement the Pa_GetStreamCpuLoad() function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double samplingPeriod;
|
||||||
|
double measurementStartTime;
|
||||||
|
double averageLoad;
|
||||||
|
} PaUtilCpuLoadMeasurer; /**< @todo need better name than measurer */
|
||||||
|
|
||||||
|
void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate );
|
||||||
|
void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer );
|
||||||
|
void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed );
|
||||||
|
void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer );
|
||||||
|
double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_CPULOAD_H */
|
||||||
204
portaudio-v19/pa_common/pa_dither.c
Normal file
204
portaudio-v19/pa_common/pa_dither.c
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library triangular dither generator
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Functions for generating dither noise
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pa_dither.h"
|
||||||
|
#include "pa_types.h"
|
||||||
|
|
||||||
|
#define PA_DITHER_BITS_ (15)
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *state )
|
||||||
|
{
|
||||||
|
state->previous = 0;
|
||||||
|
state->randSeed1 = 22222;
|
||||||
|
state->randSeed2 = 5555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *state )
|
||||||
|
{
|
||||||
|
signed long current, highPass;
|
||||||
|
|
||||||
|
/* Generate two random numbers. */
|
||||||
|
state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
|
||||||
|
state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;
|
||||||
|
|
||||||
|
/* Generate triangular distribution about 0.
|
||||||
|
* Shift before adding to prevent overflow which would skew the distribution.
|
||||||
|
* Also shift an extra bit for the high pass filter.
|
||||||
|
*/
|
||||||
|
#define DITHER_SHIFT_ ((SIZEOF_LONG*8 - PA_DITHER_BITS_) + 1)
|
||||||
|
current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
|
||||||
|
(((signed long)state->randSeed2)>>DITHER_SHIFT_);
|
||||||
|
|
||||||
|
/* High pass filter to reduce audibility. */
|
||||||
|
highPass = current - state->previous;
|
||||||
|
state->previous = current;
|
||||||
|
return highPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Multiply by PA_FLOAT_DITHER_SCALE_ to get a float between -2.0 and +1.99999 */
|
||||||
|
#define PA_FLOAT_DITHER_SCALE_ (1.0f / ((1<<PA_DITHER_BITS_)-1))
|
||||||
|
static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
|
||||||
|
|
||||||
|
float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *state )
|
||||||
|
{
|
||||||
|
signed long current, highPass;
|
||||||
|
|
||||||
|
/* Generate two random numbers. */
|
||||||
|
state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
|
||||||
|
state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;
|
||||||
|
|
||||||
|
/* Generate triangular distribution about 0.
|
||||||
|
* Shift before adding to prevent overflow which would skew the distribution.
|
||||||
|
* Also shift an extra bit for the high pass filter.
|
||||||
|
*/
|
||||||
|
#define DITHER_SHIFT_ ((SIZEOF_LONG*8 - PA_DITHER_BITS_) + 1)
|
||||||
|
current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
|
||||||
|
(((signed long)state->randSeed2)>>DITHER_SHIFT_);
|
||||||
|
|
||||||
|
/* High pass filter to reduce audibility. */
|
||||||
|
highPass = current - state->previous;
|
||||||
|
state->previous = current;
|
||||||
|
return ((float)highPass) * const_float_dither_scale_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following alternate dither algorithms (from musicdsp.org) could be
|
||||||
|
considered
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*Noise shaped dither (March 2000)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
This is a simple implementation of highpass triangular-PDF dither with
|
||||||
|
2nd-order noise shaping, for use when truncating floating point audio
|
||||||
|
data to fixed point.
|
||||||
|
|
||||||
|
The noise shaping lowers the noise floor by 11dB below 5kHz (@ 44100Hz
|
||||||
|
sample rate) compared to triangular-PDF dither. The code below assumes
|
||||||
|
input data is in the range +1 to -1 and doesn't check for overloads!
|
||||||
|
|
||||||
|
To save time when generating dither for multiple channels you can do
|
||||||
|
things like this: r3=(r1 & 0x7F)<<8; instead of calling rand() again.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int r1, r2; //rectangular-PDF random numbers
|
||||||
|
float s1, s2; //error feedback buffers
|
||||||
|
float s = 0.5f; //set to 0.0f for no noise shaping
|
||||||
|
float w = pow(2.0,bits-1); //word length (usually bits=16)
|
||||||
|
float wi= 1.0f/w;
|
||||||
|
float d = wi / RAND_MAX; //dither amplitude (2 lsb)
|
||||||
|
float o = wi * 0.5f; //remove dc offset
|
||||||
|
float in, tmp;
|
||||||
|
int out;
|
||||||
|
|
||||||
|
|
||||||
|
//for each sample...
|
||||||
|
|
||||||
|
r2=r1; //can make HP-TRI dither by
|
||||||
|
r1=rand(); //subtracting previous rand()
|
||||||
|
|
||||||
|
in += s * (s1 + s1 - s2); //error feedback
|
||||||
|
tmp = in + o + d * (float)(r1 - r2); //dc offset and dither
|
||||||
|
|
||||||
|
out = (int)(w * tmp); //truncate downwards
|
||||||
|
if(tmp<0.0f) out--; //this is faster than floor()
|
||||||
|
|
||||||
|
s2 = s1;
|
||||||
|
s1 = in - wi * (float)out; //error
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
paul.kellett@maxim.abel.co.uk
|
||||||
|
http://www.maxim.abel.co.uk
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
16-to-8-bit first-order dither
|
||||||
|
|
||||||
|
Type : First order error feedforward dithering code
|
||||||
|
References : Posted by Jon Watte
|
||||||
|
|
||||||
|
Notes :
|
||||||
|
This is about as simple a dithering algorithm as you can implement, but it's
|
||||||
|
likely to sound better than just truncating to N bits.
|
||||||
|
|
||||||
|
Note that you might not want to carry forward the full difference for infinity.
|
||||||
|
It's probably likely that the worst performance hit comes from the saturation
|
||||||
|
conditionals, which can be avoided with appropriate instructions on many DSPs
|
||||||
|
and integer SIMD type instructions, or CMOV.
|
||||||
|
|
||||||
|
Last, if sound quality is paramount (such as when going from > 16 bits to 16
|
||||||
|
bits) you probably want to use a higher-order dither function found elsewhere
|
||||||
|
on this site.
|
||||||
|
|
||||||
|
|
||||||
|
Code :
|
||||||
|
// This code will down-convert and dither a 16-bit signed short
|
||||||
|
// mono signal into an 8-bit unsigned char signal, using a first
|
||||||
|
// order forward-feeding error term dither.
|
||||||
|
|
||||||
|
#define uchar unsigned char
|
||||||
|
|
||||||
|
void dither_one_channel_16_to_8( short * input, uchar * output, int count, int * memory )
|
||||||
|
{
|
||||||
|
int m = *memory;
|
||||||
|
while( count-- > 0 ) {
|
||||||
|
int i = *input++;
|
||||||
|
i += m;
|
||||||
|
int j = i + 32768 - 128;
|
||||||
|
uchar o;
|
||||||
|
if( j < 0 ) {
|
||||||
|
o = 0;
|
||||||
|
}
|
||||||
|
else if( j > 65535 ) {
|
||||||
|
o = 255;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
o = (uchar)((j>>8)&0xff);
|
||||||
|
}
|
||||||
|
m = ((j-32768+128)-i);
|
||||||
|
*output++ = o;
|
||||||
|
}
|
||||||
|
*memory = m;
|
||||||
|
}
|
||||||
|
*/
|
||||||
91
portaudio-v19/pa_common/pa_dither.h
Normal file
91
portaudio-v19/pa_common/pa_dither.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#ifndef PA_DITHER_H
|
||||||
|
#define PA_DITHER_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library triangular dither generator
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Functions for generating dither noise
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief State needed to generate a dither signal */
|
||||||
|
typedef struct PaUtilTriangularDitherGenerator{
|
||||||
|
unsigned long previous;
|
||||||
|
unsigned long randSeed1;
|
||||||
|
unsigned long randSeed2;
|
||||||
|
} PaUtilTriangularDitherGenerator;
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Initialize dither state */
|
||||||
|
void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *ditherState );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Calculate 2 LSB dither signal with a triangular distribution.
|
||||||
|
Ranged for adding to a 1 bit right-shifted 32 bit integer
|
||||||
|
prior to >>15. eg:
|
||||||
|
<pre>
|
||||||
|
signed long in = *
|
||||||
|
signed long dither = PaUtil_Generate16BitTriangularDither( ditherState );
|
||||||
|
signed short out = (signed short)(((in>>1) + dither) >> 15);
|
||||||
|
</pre>
|
||||||
|
@return
|
||||||
|
A signed long with a range of +32767 to -32768
|
||||||
|
*/
|
||||||
|
signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Calculate 2 LSB dither signal with a triangular distribution.
|
||||||
|
Ranged for adding to a pre-scaled float.
|
||||||
|
<pre>
|
||||||
|
float in = *
|
||||||
|
float dither = PaUtil_GenerateFloatTriangularDither( ditherState );
|
||||||
|
// use smaller scaler to prevent overflow when we add the dither
|
||||||
|
signed short out = (signed short)(in*(32766.0f) + dither );
|
||||||
|
</pre>
|
||||||
|
@return
|
||||||
|
A float with a range of -2.0 to +1.99999.
|
||||||
|
*/
|
||||||
|
float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_DITHER_H */
|
||||||
111
portaudio-v19/pa_common/pa_endianness.h
Normal file
111
portaudio-v19/pa_common/pa_endianness.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#ifndef PA_ENDIANNESS_H
|
||||||
|
#define PA_ENDIANNESS_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library current platform endianness macros
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Configure endianness symbols for the target processor.
|
||||||
|
|
||||||
|
Arrange for either the PA_LITTLE_ENDIAN or PA_BIG_ENDIAN preprocessor symbols
|
||||||
|
to be defined. The one that is defined reflects the endianness of the target
|
||||||
|
platform and may be used to implement conditional compilation of byte-order
|
||||||
|
dependent code.
|
||||||
|
|
||||||
|
If either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN is defined already, then no attempt
|
||||||
|
is made to override that setting. This may be useful if you have a better way
|
||||||
|
of determining the platform's endianness. The autoconf mechanism uses this for
|
||||||
|
example.
|
||||||
|
|
||||||
|
A PA_VALIDATE_ENDIANNESS macro is provided to compare the compile time
|
||||||
|
and runtime endiannes and raise an assertion if they don't match.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(PA_LITTLE_ENDIAN) || defined(PA_BIG_ENDIAN)
|
||||||
|
/* endianness define has been set externally, such as by autoconf */
|
||||||
|
|
||||||
|
#if defined(PA_LITTLE_ENDIAN) && defined(PA_BIG_ENDIAN)
|
||||||
|
#error both PA_LITTLE_ENDIAN and PA_BIG_ENDIAN have been defined externally to pa_endianness.h - only one endianness at a time please
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* endianness define has not been set externally */
|
||||||
|
|
||||||
|
/* set PA_LITTLE_ENDIAN or PA_BIG_ENDIAN by testing well known platform specific defines */
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||||
|
|
||||||
|
#define PA_LITTLE_ENDIAN /* win32, assume intel byte order */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(PA_LITTLE_ENDIAN) && !defined(PA_BIG_ENDIAN)
|
||||||
|
/*
|
||||||
|
If the following error is raised, you either need to modify the code above
|
||||||
|
to automatically determine the endianness from other symbols defined on your
|
||||||
|
platform, or define either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN externally.
|
||||||
|
*/
|
||||||
|
#error pa_endianness.h was unable to automatically determine the endianness of the target platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* PA_VALIDATE_ENDIANNESS compares the compile time and runtime endianness,
|
||||||
|
and raises an assertion if they don't match. <assert.h> must be included in
|
||||||
|
the context in which this macro is used.
|
||||||
|
*/
|
||||||
|
#if defined(PA_LITTLE_ENDIAN)
|
||||||
|
#define PA_VALIDATE_ENDIANNESS \
|
||||||
|
{ \
|
||||||
|
const long nativeOne = 1; \
|
||||||
|
assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 1 ); \
|
||||||
|
}
|
||||||
|
#elif defined(PA_BIG_ENDIAN)
|
||||||
|
#define PA_VALIDATE_ENDIANNESS \
|
||||||
|
{ \
|
||||||
|
const long nativeOne = 1; \
|
||||||
|
assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 0 ); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_ENDIANNESS_H */
|
||||||
1978
portaudio-v19/pa_common/pa_front.c
Normal file
1978
portaudio-v19/pa_common/pa_front.c
Normal file
File diff suppressed because it is too large
Load Diff
244
portaudio-v19/pa_common/pa_hostapi.h
Normal file
244
portaudio-v19/pa_common/pa_hostapi.h
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
#ifndef PA_HOSTAPI_H
|
||||||
|
#define PA_HOSTAPI_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library
|
||||||
|
* host api representation
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
@brief Interface used by pa_front to virtualize functions which operate on
|
||||||
|
host APIs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
/** **FOR THE USE OF pa_front.c ONLY**
|
||||||
|
Do NOT use fields in this structure, they my change at any time.
|
||||||
|
Use functions defined in pa_util.h if you think you need functionality
|
||||||
|
which can be derived from here.
|
||||||
|
*/
|
||||||
|
typedef struct PaUtilPrivatePaFrontHostApiInfo {
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long baseDeviceIndex;
|
||||||
|
}PaUtilPrivatePaFrontHostApiInfo;
|
||||||
|
|
||||||
|
|
||||||
|
/** The common header for all data structures whose pointers are passed through
|
||||||
|
the hostApiSpecificStreamInfo field of the PaStreamParameters structure.
|
||||||
|
Note that in order to keep the public PortAudio interface clean, this structure
|
||||||
|
is not used explicitly when declaring hostApiSpecificStreamInfo data structures.
|
||||||
|
However, some code in pa_front depends on the first 3 members being equivalent
|
||||||
|
with this structure.
|
||||||
|
@see PaStreamParameters
|
||||||
|
*/
|
||||||
|
typedef struct PaUtilHostApiSpecificStreamInfoHeader
|
||||||
|
{
|
||||||
|
unsigned long size; /**< size of whole structure including this header */
|
||||||
|
PaHostApiTypeId hostApiType; /**< host API for which this data is intended */
|
||||||
|
unsigned long version; /**< structure version */
|
||||||
|
} PaUtilHostApiSpecificStreamInfoHeader;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A structure representing the interface to a host API. Contains both
|
||||||
|
concrete data and pointers to functions which implement the interface.
|
||||||
|
*/
|
||||||
|
typedef struct PaUtilHostApiRepresentation {
|
||||||
|
PaUtilPrivatePaFrontHostApiInfo privatePaFrontInfo;
|
||||||
|
|
||||||
|
/** The host api implementation should populate the info field. In the
|
||||||
|
case of info.defaultInputDevice and info.defaultOutputDevice the
|
||||||
|
values stored should be 0 based indices within the host api's own
|
||||||
|
device index range (0 to deviceCount). These values will be converted
|
||||||
|
to global device indices by pa_front after PaUtilHostApiInitializer()
|
||||||
|
returns.
|
||||||
|
*/
|
||||||
|
PaHostApiInfo info;
|
||||||
|
|
||||||
|
PaDeviceInfo** deviceInfos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
(*Terminate)() is guaranteed to be called with a valid <hostApi>
|
||||||
|
parameter, which was previously returned from the same implementation's
|
||||||
|
initializer.
|
||||||
|
*/
|
||||||
|
void (*Terminate)( struct PaUtilHostApiRepresentation *hostApi );
|
||||||
|
|
||||||
|
/**
|
||||||
|
The inputParameters and outputParameters pointers should not be saved
|
||||||
|
as they will not remain valid after OpenStream is called.
|
||||||
|
|
||||||
|
|
||||||
|
The following guarantees are made about parameters to (*OpenStream)():
|
||||||
|
|
||||||
|
[NOTE: the following list up to *END PA FRONT VALIDATIONS* should be
|
||||||
|
kept in sync with the one for ValidateOpenStreamParameters and
|
||||||
|
Pa_OpenStream in pa_front.c]
|
||||||
|
|
||||||
|
PaHostApiRepresentation *hostApi
|
||||||
|
- is valid for this implementation
|
||||||
|
|
||||||
|
PaStream** stream
|
||||||
|
- is non-null
|
||||||
|
|
||||||
|
- at least one of inputParameters & outputParmeters is valid (not NULL)
|
||||||
|
|
||||||
|
- if inputParameters & outputParmeters are both valid, that
|
||||||
|
inputParameters->device & outputParmeters->device both use the same host api
|
||||||
|
|
||||||
|
PaDeviceIndex inputParameters->device
|
||||||
|
- is within range (0 to Pa_CountDevices-1) Or:
|
||||||
|
- is paUseHostApiSpecificDeviceSpecification and
|
||||||
|
inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
|
||||||
|
to a valid host api
|
||||||
|
|
||||||
|
int inputParameters->numChannels
|
||||||
|
- if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, numInputChannels is > 0
|
||||||
|
- upper bound is NOT validated against device capabilities
|
||||||
|
|
||||||
|
PaSampleFormat inputParameters->sampleFormat
|
||||||
|
- is one of the sample formats defined in portaudio.h
|
||||||
|
|
||||||
|
void *inputParameters->hostApiSpecificStreamInfo
|
||||||
|
- if supplied its hostApi field matches the input device's host Api
|
||||||
|
|
||||||
|
PaDeviceIndex outputParmeters->device
|
||||||
|
- is within range (0 to Pa_CountDevices-1)
|
||||||
|
|
||||||
|
int outputParmeters->numChannels
|
||||||
|
- if inputDevice is valid, numInputChannels is > 0
|
||||||
|
- upper bound is NOT validated against device capabilities
|
||||||
|
|
||||||
|
PaSampleFormat outputParmeters->sampleFormat
|
||||||
|
- is one of the sample formats defined in portaudio.h
|
||||||
|
|
||||||
|
void *outputParmeters->hostApiSpecificStreamInfo
|
||||||
|
- if supplied its hostApi field matches the output device's host Api
|
||||||
|
|
||||||
|
double sampleRate
|
||||||
|
- is not an 'absurd' rate (less than 1000. or greater than 200000.)
|
||||||
|
- sampleRate is NOT validated against device capabilities
|
||||||
|
|
||||||
|
PaStreamFlags streamFlags
|
||||||
|
- unused platform neutral flags are zero
|
||||||
|
- paNeverDropInput is only used for full-duplex callback streams
|
||||||
|
with variable buffer size (paFramesPerBufferUnspecified)
|
||||||
|
|
||||||
|
[*END PA FRONT VALIDATIONS*]
|
||||||
|
|
||||||
|
|
||||||
|
The following validations MUST be performed by (*OpenStream)():
|
||||||
|
|
||||||
|
- check that input device can support numInputChannels
|
||||||
|
|
||||||
|
- check that input device can support inputSampleFormat, or that
|
||||||
|
we have the capability to convert from outputSampleFormat to
|
||||||
|
a native format
|
||||||
|
|
||||||
|
- if inputStreamInfo is supplied, validate its contents,
|
||||||
|
or return an error if no inputStreamInfo is expected
|
||||||
|
|
||||||
|
- check that output device can support numOutputChannels
|
||||||
|
|
||||||
|
- check that output device can support outputSampleFormat, or that
|
||||||
|
we have the capability to convert from outputSampleFormat to
|
||||||
|
a native format
|
||||||
|
|
||||||
|
- if outputStreamInfo is supplied, validate its contents,
|
||||||
|
or return an error if no outputStreamInfo is expected
|
||||||
|
|
||||||
|
- if a full duplex stream is requested, check that the combination
|
||||||
|
of input and output parameters is supported
|
||||||
|
|
||||||
|
- check that the device supports sampleRate
|
||||||
|
|
||||||
|
- alter sampleRate to a close allowable rate if necessary
|
||||||
|
|
||||||
|
- validate inputLatency and outputLatency
|
||||||
|
|
||||||
|
- validate any platform specific flags, if flags are supplied they
|
||||||
|
must be valid.
|
||||||
|
*/
|
||||||
|
PaError (*OpenStream)( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
PaStream** stream,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerCallback,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
PaStreamCallback *streamCallback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
PaError (*IsFormatSupported)( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate );
|
||||||
|
} PaUtilHostApiRepresentation;
|
||||||
|
|
||||||
|
|
||||||
|
/** Prototype for the initialization function which must be implemented by every
|
||||||
|
host API.
|
||||||
|
|
||||||
|
@see paHostApiInitializers
|
||||||
|
*/
|
||||||
|
typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostApiIndex );
|
||||||
|
|
||||||
|
|
||||||
|
/** paHostApiInitializers is a NULL-terminated array of host API initialization
|
||||||
|
functions. These functions are called by pa_front to initialize the host APIs
|
||||||
|
when the client calls Pa_Initialize().
|
||||||
|
|
||||||
|
There is a platform specific file which defines paHostApiInitializers for that
|
||||||
|
platform, pa_win/pa_win_hostapis.c contains the Win32 definitions for example.
|
||||||
|
*/
|
||||||
|
extern PaUtilHostApiInitializer *paHostApiInitializers[];
|
||||||
|
|
||||||
|
|
||||||
|
/** The index of the default host API in the paHostApiInitializers array.
|
||||||
|
|
||||||
|
There is a platform specific file which defines paDefaultHostApiIndex for that
|
||||||
|
platform, see pa_win/pa_win_hostapis.c for example.
|
||||||
|
*/
|
||||||
|
extern int paDefaultHostApiIndex;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_HOSTAPI_H */
|
||||||
1763
portaudio-v19/pa_common/pa_process.c
Normal file
1763
portaudio-v19/pa_common/pa_process.c
Normal file
File diff suppressed because it is too large
Load Diff
741
portaudio-v19/pa_common/pa_process.h
Normal file
741
portaudio-v19/pa_common/pa_process.h
Normal file
@ -0,0 +1,741 @@
|
|||||||
|
#ifndef PA_PROCESS_H
|
||||||
|
#define PA_PROCESS_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library callback buffer processing adapters
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Buffer Processor prototypes. A Buffer Processor performs buffer length
|
||||||
|
adaption, coordinates sample format conversion, and interleaves/deinterleaves
|
||||||
|
channels.
|
||||||
|
|
||||||
|
<h3>Overview</h3>
|
||||||
|
|
||||||
|
The "Buffer Processor" (PaUtilBufferProcessor) manages conversion of audio
|
||||||
|
data from host buffers to user buffers and back again. Where required, the
|
||||||
|
buffer processor takes care of converting between host and user sample formats,
|
||||||
|
interleaving and deinterleaving multichannel buffers, and adapting between host
|
||||||
|
and user buffers with different lengths. The buffer processor may be used with
|
||||||
|
full and half duplex streams, for both callback streams and blocking read/write
|
||||||
|
streams.
|
||||||
|
|
||||||
|
One of the important capabilities provided by the buffer processor is
|
||||||
|
the ability to adapt between user and host buffer sizes of different lengths
|
||||||
|
with minimum latency. Although this task is relatively easy to perform when
|
||||||
|
the host buffer size is an integer multiple of the user buffer size, the
|
||||||
|
problem is more complicated when this is not the case - especially for
|
||||||
|
full-duplex callback streams. Where necessary the adaption is implemented by
|
||||||
|
internally buffering some input and/or output data. The buffer adation
|
||||||
|
algorithm used by the buffer processor was originally implemented by
|
||||||
|
Stephan Letz for the ASIO version of PortAudio, and is described in his
|
||||||
|
Callback_adaption_.pdf which is included in the distribution.
|
||||||
|
|
||||||
|
The buffer processor performs sample conversion using the functions provided
|
||||||
|
by pa_converters.c.
|
||||||
|
|
||||||
|
The following sections provide an overview of how to use the buffer processor.
|
||||||
|
Interested readers are advised to consult the host API implementations for
|
||||||
|
examples of buffer processor usage.
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Initialization, resetting and termination</h4>
|
||||||
|
|
||||||
|
When a stream is opened, the buffer processor should be initialized using
|
||||||
|
PaUtil_InitializeBufferProcessor. This function initializes internal state
|
||||||
|
and allocates temporary buffers as neccesary according to the supplied
|
||||||
|
configuration parameters. Some of the parameters correspond to those requested
|
||||||
|
by the user in their call to Pa_OpenStream(), others reflect the requirements
|
||||||
|
of the host API implementation - they indicate host buffer sizes, formats,
|
||||||
|
and the type of buffering which the Host API uses. The buffer processor should
|
||||||
|
be initialized for callback streams and blocking read/write streams.
|
||||||
|
|
||||||
|
Call PaUtil_ResetBufferProcessor to clear any sample data which is present
|
||||||
|
in the buffer processor before starting to use it (for example when
|
||||||
|
Pa_StartStream is called).
|
||||||
|
|
||||||
|
When the buffer processor is no longer used call
|
||||||
|
PaUtil_TerminateBufferProcessor.
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Using the buffer processor for a callback stream</h4>
|
||||||
|
|
||||||
|
The buffer processor's role in a callback stream is to take host input buffers
|
||||||
|
process them with the stream callback, and fill host output buffers. For a
|
||||||
|
full duplex stream, the buffer processor handles input and output simultaneously
|
||||||
|
due to the requirements of the minimum-latency buffer adation algorithm.
|
||||||
|
|
||||||
|
When a host buffer becomes available, the implementation should call
|
||||||
|
the buffer processor to process the buffer. The buffer processor calls the
|
||||||
|
stream callback to consume and/or produce audio data as necessary. The buffer
|
||||||
|
processor will convert sample formats, interleave/deinterleave channels,
|
||||||
|
and slice or chunk the data to the appropriate buffer lengths according to
|
||||||
|
the requirements of the stream callback and the host API.
|
||||||
|
|
||||||
|
To process a host buffer (or a pair of host buffers for a full-duplex stream)
|
||||||
|
use the following calling sequence:
|
||||||
|
|
||||||
|
-# Call PaUtil_BeginBufferProcessing
|
||||||
|
-# For a stream which takes input:
|
||||||
|
- Call PaUtil_SetInputFrameCount with the number of frames in the host input
|
||||||
|
buffer.
|
||||||
|
- Call one of the following functions one or more times to tell the
|
||||||
|
buffer processor about the host input buffer(s): PaUtil_SetInputChannel,
|
||||||
|
PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel.
|
||||||
|
Which function you call will depend on whether the host buffer(s) are
|
||||||
|
interleaved or not.
|
||||||
|
- If the available host data is split accross two buffers (for example a
|
||||||
|
data range at the end of a circular buffer and another range at the
|
||||||
|
beginning of the circular buffer), also call
|
||||||
|
PaUtil_Set2ndInputFrameCount, PaUtil_Set2ndInputChannel,
|
||||||
|
PaUtil_Set2ndInterleavedInputChannels,
|
||||||
|
PaUtil_Set2ndNonInterleavedInputChannel as necessary to tell the buffer
|
||||||
|
processor about the second buffer.
|
||||||
|
-# For a stream which generates output:
|
||||||
|
- Call PaUtil_SetOutputFrameCount with the number of frames in the host
|
||||||
|
output buffer.
|
||||||
|
- Call one of the following functions one or more times to tell the
|
||||||
|
buffer processor about the host output buffer(s): PaUtil_SetOutputChannel,
|
||||||
|
PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel.
|
||||||
|
Which function you call will depend on whether the host buffer(s) are
|
||||||
|
interleaved or not.
|
||||||
|
- If the available host output buffer space is split accross two buffers
|
||||||
|
(for example a data range at the end of a circular buffer and another
|
||||||
|
range at the beginning of the circular buffer), call
|
||||||
|
PaUtil_Set2ndOutputFrameCount, PaUtil_Set2ndOutputChannel,
|
||||||
|
PaUtil_Set2ndInterleavedOutputChannels,
|
||||||
|
PaUtil_Set2ndNonInterleavedOutputChannel as necessary to tell the buffer
|
||||||
|
processor about the second buffer.
|
||||||
|
-# Call PaUtil_EndBufferProcessing, this function performs the actual data
|
||||||
|
conversion and processing.
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Using the buffer processor for a blocking read/write stream</h4>
|
||||||
|
|
||||||
|
Blocking read/write streams use the buffer processor to convert and copy user
|
||||||
|
output data to a host buffer, and to convert and copy host input data to
|
||||||
|
the user's buffer. The buffer processor does not perform any buffer adaption.
|
||||||
|
When using the buffer processor in a blocking read/write stream the input and
|
||||||
|
output conversion are performed separately by the PaUtil_CopyInput and
|
||||||
|
PaUtil_CopyOutput functions.
|
||||||
|
|
||||||
|
To copy data from a host input buffer to the buffer(s) which the user supplies
|
||||||
|
to Pa_ReadStream, use the following calling sequence.
|
||||||
|
|
||||||
|
- Repeat the following three steps until the user buffer(s) have been filled
|
||||||
|
with samples from the host input buffers:
|
||||||
|
-# Call PaUtil_SetInputFrameCount with the number of frames in the host
|
||||||
|
input buffer.
|
||||||
|
-# Call one of the following functions one or more times to tell the
|
||||||
|
buffer processor about the host input buffer(s): PaUtil_SetInputChannel,
|
||||||
|
PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel.
|
||||||
|
Which function you call will depend on whether the host buffer(s) are
|
||||||
|
interleaved or not.
|
||||||
|
-# Call PaUtil_CopyInput with the user buffer pointer (or a copy of the
|
||||||
|
array of buffer pointers for a non-interleaved stream) passed to
|
||||||
|
Pa_ReadStream, along with the number of frames in the user buffer(s).
|
||||||
|
Be careful to pass a <i>copy</i> of the user buffer pointers to
|
||||||
|
PaUtil_CopyInput because PaUtil_CopyInput advances the pointers to
|
||||||
|
the start of the next region to copy.
|
||||||
|
- PaUtil_CopyInput will not copy more data than is available in the
|
||||||
|
host buffer(s), so the above steps need to be repeated until the user
|
||||||
|
buffer(s) are full.
|
||||||
|
|
||||||
|
|
||||||
|
To copy data to the host output buffer from the user buffers(s) supplied
|
||||||
|
to Pa_WriteStream use the following calling sequence.
|
||||||
|
|
||||||
|
- Repeat the following three steps until all frames from the user buffer(s)
|
||||||
|
have been copied to the host API:
|
||||||
|
-# Call PaUtil_SetOutputFrameCount with the number of frames in the host
|
||||||
|
output buffer.
|
||||||
|
-# Call one of the following functions one or more times to tell the
|
||||||
|
buffer processor about the host output buffer(s): PaUtil_SetOutputChannel,
|
||||||
|
PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel.
|
||||||
|
Which function you call will depend on whether the host buffer(s) are
|
||||||
|
interleaved or not.
|
||||||
|
-# Call PaUtil_CopyOutput with the user buffer pointer (or a copy of the
|
||||||
|
array of buffer pointers for a non-interleaved stream) passed to
|
||||||
|
Pa_WriteStream, along with the number of frames in the user buffer(s).
|
||||||
|
Be careful to pass a <i>copy</i> of the user buffer pointers to
|
||||||
|
PaUtil_CopyOutput because PaUtil_CopyOutput advances the pointers to
|
||||||
|
the start of the next region to copy.
|
||||||
|
- PaUtil_CopyOutput will not copy more data than fits in the host buffer(s),
|
||||||
|
so the above steps need to be repeated until all user data is copied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
#include "pa_converters.h"
|
||||||
|
#include "pa_dither.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Mode flag passed to PaUtil_InitializeBufferProcessor indicating the type
|
||||||
|
of buffering that the host API uses.
|
||||||
|
|
||||||
|
The mode used depends on whether the host API or the implementation manages
|
||||||
|
the buffers, and how these buffers are used (scatter gather, circular buffer).
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/** The host buffer size is a fixed known size. */
|
||||||
|
paUtilFixedHostBufferSize,
|
||||||
|
|
||||||
|
/** The host buffer size may vary, but has a known maximum size. */
|
||||||
|
paUtilBoundedHostBufferSize,
|
||||||
|
|
||||||
|
/** Nothing is known about the host buffer size. */
|
||||||
|
paUtilUnknownHostBufferSize,
|
||||||
|
|
||||||
|
/** The host buffer size varies, and the client does not require the buffer
|
||||||
|
processor to consume all of the input and fill all of the output buffer. This
|
||||||
|
is useful when the implementation has access to the host API's circular buffer
|
||||||
|
and only needs to consume/fill some of it, not necessarily all of it, with each
|
||||||
|
call to the buffer processor. This is the only mode where
|
||||||
|
PaUtil_EndBufferProcessing() may not consume the whole buffer.
|
||||||
|
*/
|
||||||
|
paUtilVariableHostBufferSizePartialUsageAllowed
|
||||||
|
}PaUtilHostBufferSizeMode;
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief An auxilliary data structure used internally by the buffer processor
|
||||||
|
to represent host input and output buffers. */
|
||||||
|
typedef struct PaUtilChannelDescriptor{
|
||||||
|
void *data;
|
||||||
|
unsigned int stride; /**< stride in samples, not bytes */
|
||||||
|
}PaUtilChannelDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief The main buffer processor data structure.
|
||||||
|
|
||||||
|
Allocate one of these, initialize it with PaUtil_InitializeBufferProcessor
|
||||||
|
and terminate it with PaUtil_TerminateBufferProcessor.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
unsigned long framesPerUserBuffer;
|
||||||
|
unsigned long framesPerHostBuffer;
|
||||||
|
|
||||||
|
PaUtilHostBufferSizeMode hostBufferSizeMode;
|
||||||
|
int useNonAdaptingProcess;
|
||||||
|
unsigned long framesPerTempBuffer;
|
||||||
|
|
||||||
|
unsigned int inputChannelCount;
|
||||||
|
unsigned int bytesPerHostInputSample;
|
||||||
|
unsigned int bytesPerUserInputSample;
|
||||||
|
int userInputIsInterleaved;
|
||||||
|
PaUtilConverter *inputConverter;
|
||||||
|
PaUtilZeroer *inputZeroer;
|
||||||
|
|
||||||
|
unsigned int outputChannelCount;
|
||||||
|
unsigned int bytesPerHostOutputSample;
|
||||||
|
unsigned int bytesPerUserOutputSample;
|
||||||
|
int userOutputIsInterleaved;
|
||||||
|
PaUtilConverter *outputConverter;
|
||||||
|
PaUtilZeroer *outputZeroer;
|
||||||
|
|
||||||
|
unsigned long initialFramesInTempInputBuffer;
|
||||||
|
unsigned long initialFramesInTempOutputBuffer;
|
||||||
|
|
||||||
|
void *tempInputBuffer; /**< used for slips, block adaption, and conversion. */
|
||||||
|
void **tempInputBufferPtrs; /**< storage for non-interleaved buffer pointers, NULL for interleaved user input */
|
||||||
|
unsigned long framesInTempInputBuffer; /**< frames remaining in input buffer from previous adaption iteration */
|
||||||
|
|
||||||
|
void *tempOutputBuffer; /**< used for slips, block adaption, and conversion. */
|
||||||
|
void **tempOutputBufferPtrs; /**< storage for non-interleaved buffer pointers, NULL for interleaved user output */
|
||||||
|
unsigned long framesInTempOutputBuffer; /**< frames remaining in input buffer from previous adaption iteration */
|
||||||
|
|
||||||
|
PaStreamCallbackTimeInfo *timeInfo;
|
||||||
|
|
||||||
|
PaStreamCallbackFlags callbackStatusFlags;
|
||||||
|
|
||||||
|
unsigned long hostInputFrameCount[2];
|
||||||
|
PaUtilChannelDescriptor *hostInputChannels[2]; /**< pointers to arrays of channel descriptors.
|
||||||
|
pointers are NULL for half-duplex output processing.
|
||||||
|
hostInputChannels[i].data is NULL when the caller
|
||||||
|
calls PaUtil_SetNoInput()
|
||||||
|
*/
|
||||||
|
unsigned long hostOutputFrameCount[2];
|
||||||
|
PaUtilChannelDescriptor *hostOutputChannels[2]; /**< pointers to arrays of channel descriptors.
|
||||||
|
pointers are NULL for half-duplex input processing.
|
||||||
|
hostOutputChannels[i].data is NULL when the caller
|
||||||
|
calls PaUtil_SetNoOutput()
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaUtilTriangularDitherGenerator ditherGenerator;
|
||||||
|
|
||||||
|
double samplePeriod;
|
||||||
|
|
||||||
|
PaStreamCallback *streamCallback;
|
||||||
|
void *userData;
|
||||||
|
} PaUtilBufferProcessor;
|
||||||
|
|
||||||
|
|
||||||
|
/** @name Initialization, termination, resetting and info */
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/** Initialize a buffer processor's representation stored in a
|
||||||
|
PaUtilBufferProcessor structure. Be sure to call
|
||||||
|
PaUtil_TerminateBufferProcessor after finishing with a buffer processor.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor structure to initialize.
|
||||||
|
|
||||||
|
@param inputChannelCount The number of input channels as passed to
|
||||||
|
Pa_OpenStream or 0 for an output-only stream.
|
||||||
|
|
||||||
|
@param userInputSampleFormat Format of user input samples, as passed to
|
||||||
|
Pa_OpenStream. This parameter is ignored for ouput-only streams.
|
||||||
|
|
||||||
|
@param hostInputSampleFormat Format of host input samples. This parameter is
|
||||||
|
ignored for output-only streams. See note about host buffer interleave below.
|
||||||
|
|
||||||
|
@param outputChannelCount The number of output channels as passed to
|
||||||
|
Pa_OpenStream or 0 for an input-only stream.
|
||||||
|
|
||||||
|
@param userOutputSampleFormat Format of user output samples, as passed to
|
||||||
|
Pa_OpenStream. This parameter is ignored for input-only streams.
|
||||||
|
|
||||||
|
@param hostOutputSampleFormat Format of host output samples. This parameter is
|
||||||
|
ignored for input-only streams. See note about host buffer interleave below.
|
||||||
|
|
||||||
|
@param sampleRate Sample rate of the stream. The more accurate this is the
|
||||||
|
better - it is used for updating time stamps when adapting buffers.
|
||||||
|
|
||||||
|
@param streamFlags Stream flags as passed to Pa_OpenStream, this parameter is
|
||||||
|
used for selecting special sample conversion options such as clipping and
|
||||||
|
dithering.
|
||||||
|
|
||||||
|
@param framesPerUserBuffer Number of frames per user buffer, as requested
|
||||||
|
by the framesPerBuffer parameter to Pa_OpenStream. This parameter may be
|
||||||
|
zero to indicate that the user will accept any (and varying) buffer sizes.
|
||||||
|
|
||||||
|
@param framesPerHostBuffer Specifies the number of frames per host buffer
|
||||||
|
for the fixed buffer size mode, and the maximum number of frames
|
||||||
|
per host buffer for the bounded host buffer size mode. It is ignored for
|
||||||
|
the other modes.
|
||||||
|
|
||||||
|
@param hostBufferSizeMode A mode flag indicating the size variability of
|
||||||
|
host buffers that will be passed to the buffer processor. See
|
||||||
|
PaUtilHostBufferSizeMode for further details.
|
||||||
|
|
||||||
|
@param streamCallback The user stream callback passed to Pa_OpenStream.
|
||||||
|
|
||||||
|
@param userData The user data field passed to Pa_OpenStream.
|
||||||
|
|
||||||
|
@note The interleave flag is ignored for host buffer formats. Host
|
||||||
|
interleave is determined by the use of different SetInput and SetOutput
|
||||||
|
functions.
|
||||||
|
|
||||||
|
@return An error code indicating whether the initialization was successful.
|
||||||
|
If the error code is not PaNoError, the buffer processor was not initialized
|
||||||
|
and should not be used.
|
||||||
|
|
||||||
|
@see Pa_OpenStream, PaUtilHostBufferSizeMode, PaUtil_TerminateBufferProcessor
|
||||||
|
*/
|
||||||
|
PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
int inputChannelCount, PaSampleFormat userInputSampleFormat,
|
||||||
|
PaSampleFormat hostInputSampleFormat,
|
||||||
|
int outputChannelCount, PaSampleFormat userOutputSampleFormat,
|
||||||
|
PaSampleFormat hostOutputSampleFormat,
|
||||||
|
double sampleRate,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
unsigned long framesPerUserBuffer, /* 0 indicates don't care */
|
||||||
|
unsigned long framesPerHostBuffer,
|
||||||
|
PaUtilHostBufferSizeMode hostBufferSizeMode,
|
||||||
|
PaStreamCallback *streamCallback, void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
/** Terminate a buffer processor's representation. Deallocates any temporary
|
||||||
|
buffers allocated by PaUtil_InitializeBufferProcessor.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor structure to terminate.
|
||||||
|
|
||||||
|
@see PaUtil_InitializeBufferProcessor.
|
||||||
|
*/
|
||||||
|
void PaUtil_TerminateBufferProcessor( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
|
||||||
|
/** Clear any internally buffered data. If you call
|
||||||
|
PaUtil_InitializeBufferProcessor in your OpenStream routine, make sure you
|
||||||
|
call PaUtil_ResetBufferProcessor in your StartStream call.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor to reset.
|
||||||
|
*/
|
||||||
|
void PaUtil_ResetBufferProcessor( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
|
||||||
|
/** Retrieve the input latency of a buffer processor.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor examine.
|
||||||
|
|
||||||
|
@return The input latency introduced by the buffer processor, in frames.
|
||||||
|
|
||||||
|
@see PaUtil_GetBufferProcessorOutputLatency
|
||||||
|
*/
|
||||||
|
unsigned long PaUtil_GetBufferProcessorInputLatency( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
/** Retrieve the output latency of a buffer processor.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor examine.
|
||||||
|
|
||||||
|
@return The output latency introduced by the buffer processor, in frames.
|
||||||
|
|
||||||
|
@see PaUtil_GetBufferProcessorInputLatency
|
||||||
|
*/
|
||||||
|
unsigned long PaUtil_GetBufferProcessorOutputLatency( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @name Host buffer pointer configuration
|
||||||
|
|
||||||
|
Functions to set host input and output buffers, used by both callback streams
|
||||||
|
and blocking read/write streams.
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
|
||||||
|
/** Set the number of frames in the input host buffer(s) specified by the
|
||||||
|
PaUtil_Set*InputChannel functions.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param frameCount The number of host input frames. A 0 frameCount indicates to
|
||||||
|
use the framesPerHostBuffer value passed to PaUtil_InitializeBufferProcessor.
|
||||||
|
|
||||||
|
@see PaUtil_SetNoInput, PaUtil_SetInputChannel,
|
||||||
|
PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel
|
||||||
|
*/
|
||||||
|
void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned long frameCount );
|
||||||
|
|
||||||
|
|
||||||
|
/** Indicate that no input is avalable. This function should be used when
|
||||||
|
priming the output of a full-duplex stream opened with the
|
||||||
|
paPrimeOutputBuffersUsingStreamCallback flag. Note that it is not necessary
|
||||||
|
to call this or any othe PaUtil_Set*Input* functions for ouput-only streams.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetNoInput( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide the buffer processor with a pointer to a host input channel.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
@param channel The channel number.
|
||||||
|
@param data The buffer.
|
||||||
|
@param stride The stride from one sample to the next, in samples. For
|
||||||
|
interleaved host buffers, the stride will usually be the same as the number of
|
||||||
|
channels in the buffer.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetInputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data, unsigned int stride );
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide the buffer processor with a pointer to an number of interleaved
|
||||||
|
host input channels.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
@param firstChannel The first channel number.
|
||||||
|
@param data The buffer.
|
||||||
|
@param channelCount The number of interleaved channels in the buffer. If
|
||||||
|
channelCount is zero, the number of channels specified to
|
||||||
|
PaUtil_InitializeBufferProcessor will be used.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetInterleavedInputChannels( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int firstChannel, void *data, unsigned int channelCount );
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide the buffer processor with a pointer to one non-interleaved host
|
||||||
|
output channel.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
@param channel The channel number.
|
||||||
|
@param data The buffer.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data );
|
||||||
|
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the input buffer is split in two halves.
|
||||||
|
@see PaUtil_SetInputFrameCount
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndInputFrameCount( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned long frameCount );
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the input buffer is split in two halves.
|
||||||
|
@see PaUtil_SetInputChannel
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndInputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data, unsigned int stride );
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the input buffer is split in two halves.
|
||||||
|
@see PaUtil_SetInterleavedInputChannels
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int firstChannel, void *data, unsigned int channelCount );
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the input buffer is split in two halves.
|
||||||
|
@see PaUtil_SetNonInterleavedInputChannel
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data );
|
||||||
|
|
||||||
|
|
||||||
|
/** Set the number of frames in the output host buffer(s) specified by the
|
||||||
|
PaUtil_Set*OutputChannel functions.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param frameCount The number of host output frames. A 0 frameCount indicates to
|
||||||
|
use the framesPerHostBuffer value passed to PaUtil_InitializeBufferProcessor.
|
||||||
|
|
||||||
|
@see PaUtil_SetOutputChannel, PaUtil_SetInterleavedOutputChannels,
|
||||||
|
PaUtil_SetNonInterleavedOutputChannel
|
||||||
|
*/
|
||||||
|
void PaUtil_SetOutputFrameCount( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned long frameCount );
|
||||||
|
|
||||||
|
|
||||||
|
/** Indicate that the output will be discarded. This function should be used
|
||||||
|
when implementing the paNeverDropInput mode for full duplex streams.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetNoOutput( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide the buffer processor with a pointer to a host output channel.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
@param channel The channel number.
|
||||||
|
@param data The buffer.
|
||||||
|
@param stride The stride from one sample to the next, in samples. For
|
||||||
|
interleaved host buffers, the stride will usually be the same as the number of
|
||||||
|
channels in the buffer.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetOutputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data, unsigned int stride );
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide the buffer processor with a pointer to a number of interleaved
|
||||||
|
host output channels.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
@param firstChannel The first channel number.
|
||||||
|
@param data The buffer.
|
||||||
|
@param channelCount The number of interleaved channels in the buffer. If
|
||||||
|
channelCount is zero, the number of channels specified to
|
||||||
|
PaUtil_InitializeBufferProcessor will be used.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int firstChannel, void *data, unsigned int channelCount );
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide the buffer processor with a pointer to one non-interleaved host
|
||||||
|
output channel.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
@param channel The channel number.
|
||||||
|
@param data The buffer.
|
||||||
|
*/
|
||||||
|
void PaUtil_SetNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data );
|
||||||
|
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the output buffer is split in two halves.
|
||||||
|
@see PaUtil_SetOutputFrameCount
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndOutputFrameCount( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned long frameCount );
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the output buffer is split in two halves.
|
||||||
|
@see PaUtil_SetOutputChannel
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndOutputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data, unsigned int stride );
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the output buffer is split in two halves.
|
||||||
|
@see PaUtil_SetInterleavedOutputChannels
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int firstChannel, void *data, unsigned int channelCount );
|
||||||
|
|
||||||
|
/** Use for the second buffer half when the output buffer is split in two halves.
|
||||||
|
@see PaUtil_SetNonInterleavedOutputChannel
|
||||||
|
*/
|
||||||
|
void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned int channel, void *data );
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @name Buffer processing functions for callback streams
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/** Commence processing a host buffer (or a pair of host buffers in the
|
||||||
|
full-duplex case) for a callback stream.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param timeInfo Timing information for the first sample of the host
|
||||||
|
buffer(s). This information may be adjusted when buffer adaption is being
|
||||||
|
performed.
|
||||||
|
|
||||||
|
@param callbackStatusFlags Flags indicating whether underruns and overruns
|
||||||
|
have occurred since the last time the buffer processor was called.
|
||||||
|
*/
|
||||||
|
void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags callbackStatusFlags );
|
||||||
|
|
||||||
|
|
||||||
|
/** Finish processing a host buffer (or a pair of host buffers in the
|
||||||
|
full-duplex case) for a callback stream.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param callbackResult On input, indicates a previous callback result, and on
|
||||||
|
exit, the result of the user stream callback, if it is called.
|
||||||
|
On entry callbackResult should contain one of { paContinue, paComplete, or
|
||||||
|
paAbort}. If paComplete is passed, the stream callback will not be called
|
||||||
|
but any audio that was generated by previous stream callbacks will be copied
|
||||||
|
to the output buffer(s). You can check whether the buffer processor's internal
|
||||||
|
buffer is empty by calling PaUtil_IsBufferProcessorOutputEmpty.
|
||||||
|
|
||||||
|
If the stream callback is called its result is stored in *callbackResult. If
|
||||||
|
the stream callback returns paComplete or paAbort, all output buffers will be
|
||||||
|
full of valid data - some of which may be zeros to acount for data that
|
||||||
|
wasn't generated by the terminating callback.
|
||||||
|
|
||||||
|
@return The number of frames processed. This usually corresponds to the
|
||||||
|
number of frames specified by the PaUtil_Set*FrameCount functions, exept in
|
||||||
|
the paUtilVariableHostBufferSizePartialUsageAllowed buffer size mode when a
|
||||||
|
smaller value may be returned.
|
||||||
|
*/
|
||||||
|
unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
int *callbackResult );
|
||||||
|
|
||||||
|
|
||||||
|
/** Determine whether any callback generated output remains in the bufffer
|
||||||
|
processor's internal buffers. This method may be used to determine when to
|
||||||
|
continue calling PaUtil_EndBufferProcessing() after the callback has returned
|
||||||
|
a callbackResult of paComplete.
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@return Returns non-zero when callback generated output remains in the internal
|
||||||
|
buffer and zero (0) when there internal buffer contains no callback generated
|
||||||
|
data.
|
||||||
|
*/
|
||||||
|
int PaUtil_IsBufferProcessorOutputEmpty( PaUtilBufferProcessor* bufferProcessor );
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @name Buffer processing functions for blocking read/write streams
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/** Copy samples from host input channels set up by the PaUtil_Set*InputChannels
|
||||||
|
functions to a user supplied buffer. This function is intended for use with
|
||||||
|
blocking read/write streams. Copies the minimum of the number of
|
||||||
|
user frames (specified by the frameCount parameter) and the number of available
|
||||||
|
host frames (specified in a previous call to SetInputFrameCount()).
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param buffer A pointer to the user buffer pointer, or a pointer to a pointer
|
||||||
|
to an array of user buffer pointers for a non-interleaved stream. It is
|
||||||
|
important that this parameter points to a copy of the user buffer pointers,
|
||||||
|
not to the actual user buffer pointers, because this function updates the
|
||||||
|
pointers before returning.
|
||||||
|
|
||||||
|
@param frameCount The number of frames of data in the buffer(s) pointed to by
|
||||||
|
the buffer parameter.
|
||||||
|
|
||||||
|
@return The number of frames copied. The buffer pointer(s) pointed to by the
|
||||||
|
buffer parameter are advanced to point to the frame(s) following the last one
|
||||||
|
filled.
|
||||||
|
*/
|
||||||
|
unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
void **buffer, unsigned long frameCount );
|
||||||
|
|
||||||
|
|
||||||
|
/* Copy samples from a user supplied buffer to host output channels set up by
|
||||||
|
the PaUtil_Set*OutputChannels functions. This function is intended for use with
|
||||||
|
blocking read/write streams. Copies the minimum of the number of
|
||||||
|
user frames (specified by the frameCount parameter) and the number of
|
||||||
|
host frames (specified in a previous call to SetOutputFrameCount()).
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param buffer A pointer to the user buffer pointer, or a pointer to a pointer
|
||||||
|
to an array of user buffer pointers for a non-interleaved stream. It is
|
||||||
|
important that this parameter points to a copy of the user buffer pointers,
|
||||||
|
not to the actual user buffer pointers, because this function updates the
|
||||||
|
pointers before returning.
|
||||||
|
|
||||||
|
@param frameCount The number of frames of data in the buffer(s) pointed to by
|
||||||
|
the buffer parameter.
|
||||||
|
|
||||||
|
@return The number of frames copied. The buffer pointer(s) pointed to by the
|
||||||
|
buffer parameter are advanced to point to the frame(s) following the last one
|
||||||
|
copied.
|
||||||
|
*/
|
||||||
|
unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
const void ** buffer, unsigned long frameCount );
|
||||||
|
|
||||||
|
|
||||||
|
/* Zero samples in host output channels set up by the PaUtil_Set*OutputChannels
|
||||||
|
functions. This function is useful for flushing streams.
|
||||||
|
Zeros the minimum of frameCount and the number of host frames specified in a
|
||||||
|
previous call to SetOutputFrameCount().
|
||||||
|
|
||||||
|
@param bufferProcessor The buffer processor.
|
||||||
|
|
||||||
|
@param frameCount The maximum number of frames to zero.
|
||||||
|
|
||||||
|
@return The number of frames zeroed.
|
||||||
|
*/
|
||||||
|
unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bufferProcessor,
|
||||||
|
unsigned long frameCount );
|
||||||
|
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_PROCESS_H */
|
||||||
807
portaudio-v19/pa_common/pa_skeleton.c
Normal file
807
portaudio-v19/pa_common/pa_skeleton.c
Normal file
@ -0,0 +1,807 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library skeleton implementation
|
||||||
|
* demonstrates how to use the common functions to implement support
|
||||||
|
* for a host API
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
@brief Skeleton implementation of support for a host API.
|
||||||
|
|
||||||
|
@note This file is provided as a starting point for implementing support for
|
||||||
|
a new host API. IMPLEMENT ME comments are used to indicate functionality
|
||||||
|
which much be customised for each implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h> /* strlen() */
|
||||||
|
|
||||||
|
#include "pa_util.h"
|
||||||
|
#include "pa_allocation.h"
|
||||||
|
#include "pa_hostapi.h"
|
||||||
|
#include "pa_stream.h"
|
||||||
|
#include "pa_cpuload.h"
|
||||||
|
#include "pa_process.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes for functions declared in this file */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
|
||||||
|
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate );
|
||||||
|
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
PaStream** s,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
PaStreamCallback *streamCallback,
|
||||||
|
void *userData );
|
||||||
|
static PaError CloseStream( PaStream* stream );
|
||||||
|
static PaError StartStream( PaStream *stream );
|
||||||
|
static PaError StopStream( PaStream *stream );
|
||||||
|
static PaError AbortStream( PaStream *stream );
|
||||||
|
static PaError IsStreamStopped( PaStream *s );
|
||||||
|
static PaError IsStreamActive( PaStream *stream );
|
||||||
|
static PaTime GetStreamTime( PaStream *stream );
|
||||||
|
static double GetStreamCpuLoad( PaStream* stream );
|
||||||
|
static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
|
||||||
|
static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
|
||||||
|
static signed long GetStreamReadAvailable( PaStream* stream );
|
||||||
|
static signed long GetStreamWriteAvailable( PaStream* stream );
|
||||||
|
|
||||||
|
|
||||||
|
/* IMPLEMENT ME: a macro like the following one should be used for reporting
|
||||||
|
host errors */
|
||||||
|
#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
|
||||||
|
PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
|
||||||
|
|
||||||
|
/* PaSkeletonHostApiRepresentation - host api datastructure specific to this implementation */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PaUtilHostApiRepresentation inheritedHostApiRep;
|
||||||
|
PaUtilStreamInterface callbackStreamInterface;
|
||||||
|
PaUtilStreamInterface blockingStreamInterface;
|
||||||
|
|
||||||
|
PaUtilAllocationGroup *allocations;
|
||||||
|
|
||||||
|
/* implementation specific data goes here */
|
||||||
|
}
|
||||||
|
PaSkeletonHostApiRepresentation; /* IMPLEMENT ME: rename this */
|
||||||
|
|
||||||
|
|
||||||
|
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
int i, deviceCount;
|
||||||
|
PaSkeletonHostApiRepresentation *skeletonHostApi;
|
||||||
|
PaDeviceInfo *deviceInfoArray;
|
||||||
|
|
||||||
|
skeletonHostApi = (PaSkeletonHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaSkeletonHostApiRepresentation) );
|
||||||
|
if( !skeletonHostApi )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeletonHostApi->allocations = PaUtil_CreateAllocationGroup();
|
||||||
|
if( !skeletonHostApi->allocations )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hostApi = &skeletonHostApi->inheritedHostApiRep;
|
||||||
|
(*hostApi)->info.structVersion = 1;
|
||||||
|
(*hostApi)->info.type = paInDevelopment; /* IMPLEMENT ME: change to correct type id */
|
||||||
|
(*hostApi)->info.name = "skeleton implementation"; /* IMPLEMENT ME: change to correct name */
|
||||||
|
|
||||||
|
(*hostApi)->info.defaultInputDevice = paNoDevice; /* IMPLEMENT ME */
|
||||||
|
(*hostApi)->info.defaultOutputDevice = paNoDevice; /* IMPLEMENT ME */
|
||||||
|
|
||||||
|
(*hostApi)->info.deviceCount = 0;
|
||||||
|
|
||||||
|
deviceCount = 0; /* IMPLEMENT ME */
|
||||||
|
|
||||||
|
if( deviceCount > 0 )
|
||||||
|
{
|
||||||
|
(*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
|
||||||
|
skeletonHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
|
||||||
|
if( !(*hostApi)->deviceInfos )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate all device info structs in a contiguous block */
|
||||||
|
deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
|
||||||
|
skeletonHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
|
||||||
|
if( !deviceInfoArray )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i=0; i < deviceCount; ++i )
|
||||||
|
{
|
||||||
|
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
||||||
|
deviceInfo->structVersion = 2;
|
||||||
|
deviceInfo->hostApi = hostApiIndex;
|
||||||
|
deviceInfo->name = 0; /* IMPLEMENT ME: allocate block and copy name eg:
|
||||||
|
deviceName = (char*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, strlen(srcName) + 1 );
|
||||||
|
if( !deviceName )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
strcpy( deviceName, srcName );
|
||||||
|
deviceInfo->name = deviceName;
|
||||||
|
*/
|
||||||
|
|
||||||
|
deviceInfo->maxInputChannels = 0; /* IMPLEMENT ME */
|
||||||
|
deviceInfo->maxOutputChannels = 0; /* IMPLEMENT ME */
|
||||||
|
|
||||||
|
deviceInfo->defaultLowInputLatency = 0.; /* IMPLEMENT ME */
|
||||||
|
deviceInfo->defaultLowOutputLatency = 0.; /* IMPLEMENT ME */
|
||||||
|
deviceInfo->defaultHighInputLatency = 0.; /* IMPLEMENT ME */
|
||||||
|
deviceInfo->defaultHighOutputLatency = 0.; /* IMPLEMENT ME */
|
||||||
|
|
||||||
|
deviceInfo->defaultSampleRate = 0.; /* IMPLEMENT ME */
|
||||||
|
|
||||||
|
(*hostApi)->deviceInfos[i] = deviceInfo;
|
||||||
|
++(*hostApi)->info.deviceCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*hostApi)->Terminate = Terminate;
|
||||||
|
(*hostApi)->OpenStream = OpenStream;
|
||||||
|
(*hostApi)->IsFormatSupported = IsFormatSupported;
|
||||||
|
|
||||||
|
PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
|
||||||
|
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
|
||||||
|
GetStreamTime, GetStreamCpuLoad,
|
||||||
|
PaUtil_DummyRead, PaUtil_DummyWrite,
|
||||||
|
PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
|
||||||
|
|
||||||
|
PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface, CloseStream, StartStream,
|
||||||
|
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
|
||||||
|
GetStreamTime, PaUtil_DummyGetCpuLoad,
|
||||||
|
ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if( skeletonHostApi )
|
||||||
|
{
|
||||||
|
if( skeletonHostApi->allocations )
|
||||||
|
{
|
||||||
|
PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
|
||||||
|
PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_FreeMemory( skeletonHostApi );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
|
||||||
|
{
|
||||||
|
PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME:
|
||||||
|
- clean up any resources not handled by the allocation group
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( skeletonHostApi->allocations )
|
||||||
|
{
|
||||||
|
PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
|
||||||
|
PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_FreeMemory( skeletonHostApi );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate )
|
||||||
|
{
|
||||||
|
int inputChannelCount, outputChannelCount;
|
||||||
|
PaSampleFormat inputSampleFormat, outputSampleFormat;
|
||||||
|
|
||||||
|
if( inputParameters )
|
||||||
|
{
|
||||||
|
inputChannelCount = inputParameters->channelCount;
|
||||||
|
inputSampleFormat = inputParameters->sampleFormat;
|
||||||
|
|
||||||
|
/* all standard sample formats are supported by the buffer adapter,
|
||||||
|
this implementation doesn't support any custom sample formats */
|
||||||
|
if( inputSampleFormat & paCustomFormat )
|
||||||
|
return paSampleFormatNotSupported;
|
||||||
|
|
||||||
|
/* unless alternate device specification is supported, reject the use of
|
||||||
|
paUseHostApiSpecificDeviceSpecification */
|
||||||
|
|
||||||
|
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
/* check that input device can support inputChannelCount */
|
||||||
|
if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
|
||||||
|
return paInvalidChannelCount;
|
||||||
|
|
||||||
|
/* validate inputStreamInfo */
|
||||||
|
if( inputParameters->hostApiSpecificStreamInfo )
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inputChannelCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( outputParameters )
|
||||||
|
{
|
||||||
|
outputChannelCount = outputParameters->channelCount;
|
||||||
|
outputSampleFormat = outputParameters->sampleFormat;
|
||||||
|
|
||||||
|
/* all standard sample formats are supported by the buffer adapter,
|
||||||
|
this implementation doesn't support any custom sample formats */
|
||||||
|
if( outputSampleFormat & paCustomFormat )
|
||||||
|
return paSampleFormatNotSupported;
|
||||||
|
|
||||||
|
/* unless alternate device specification is supported, reject the use of
|
||||||
|
paUseHostApiSpecificDeviceSpecification */
|
||||||
|
|
||||||
|
if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
/* check that output device can support outputChannelCount */
|
||||||
|
if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
|
||||||
|
return paInvalidChannelCount;
|
||||||
|
|
||||||
|
/* validate outputStreamInfo */
|
||||||
|
if( outputParameters->hostApiSpecificStreamInfo )
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputChannelCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME:
|
||||||
|
|
||||||
|
- if a full duplex stream is requested, check that the combination
|
||||||
|
of input and output parameters is supported if necessary
|
||||||
|
|
||||||
|
- check that the device supports sampleRate
|
||||||
|
|
||||||
|
Because the buffer adapter handles conversion between all standard
|
||||||
|
sample formats, the following checks are only required if paCustomFormat
|
||||||
|
is implemented, or under some other unusual conditions.
|
||||||
|
|
||||||
|
- check that input device can support inputSampleFormat, or that
|
||||||
|
we have the capability to convert from inputSampleFormat to
|
||||||
|
a native format
|
||||||
|
|
||||||
|
- check that output device can support outputSampleFormat, or that
|
||||||
|
we have the capability to convert from outputSampleFormat to
|
||||||
|
a native format
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) sampleRate;
|
||||||
|
|
||||||
|
return paFormatIsSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaSkeletonStream - a stream data structure specifically for this implementation */
|
||||||
|
|
||||||
|
typedef struct PaSkeletonStream
|
||||||
|
{ /* IMPLEMENT ME: rename this */
|
||||||
|
PaUtilStreamRepresentation streamRepresentation;
|
||||||
|
PaUtilCpuLoadMeasurer cpuLoadMeasurer;
|
||||||
|
PaUtilBufferProcessor bufferProcessor;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME:
|
||||||
|
- implementation specific data goes here
|
||||||
|
*/
|
||||||
|
unsigned long framesPerHostCallback; /* just an example */
|
||||||
|
}
|
||||||
|
PaSkeletonStream;
|
||||||
|
|
||||||
|
/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
|
||||||
|
|
||||||
|
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
PaStream** s,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
PaStreamCallback *streamCallback,
|
||||||
|
void *userData )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
|
||||||
|
PaSkeletonStream *stream = 0;
|
||||||
|
unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */
|
||||||
|
int inputChannelCount, outputChannelCount;
|
||||||
|
PaSampleFormat inputSampleFormat, outputSampleFormat;
|
||||||
|
PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
|
||||||
|
|
||||||
|
|
||||||
|
if( inputParameters )
|
||||||
|
{
|
||||||
|
inputChannelCount = inputParameters->channelCount;
|
||||||
|
inputSampleFormat = inputParameters->sampleFormat;
|
||||||
|
|
||||||
|
/* unless alternate device specification is supported, reject the use of
|
||||||
|
paUseHostApiSpecificDeviceSpecification */
|
||||||
|
|
||||||
|
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
/* check that input device can support inputChannelCount */
|
||||||
|
if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
|
||||||
|
return paInvalidChannelCount;
|
||||||
|
|
||||||
|
/* validate inputStreamInfo */
|
||||||
|
if( inputParameters->hostApiSpecificStreamInfo )
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
|
||||||
|
|
||||||
|
/* IMPLEMENT ME - establish which host formats are available */
|
||||||
|
hostInputSampleFormat =
|
||||||
|
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inputChannelCount = 0;
|
||||||
|
inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if( outputParameters )
|
||||||
|
{
|
||||||
|
outputChannelCount = outputParameters->channelCount;
|
||||||
|
outputSampleFormat = outputParameters->sampleFormat;
|
||||||
|
|
||||||
|
/* unless alternate device specification is supported, reject the use of
|
||||||
|
paUseHostApiSpecificDeviceSpecification */
|
||||||
|
|
||||||
|
if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
/* check that output device can support inputChannelCount */
|
||||||
|
if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
|
||||||
|
return paInvalidChannelCount;
|
||||||
|
|
||||||
|
/* validate outputStreamInfo */
|
||||||
|
if( outputParameters->hostApiSpecificStreamInfo )
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
|
||||||
|
|
||||||
|
/* IMPLEMENT ME - establish which host formats are available */
|
||||||
|
hostOutputSampleFormat =
|
||||||
|
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputChannelCount = 0;
|
||||||
|
outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME:
|
||||||
|
|
||||||
|
( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )
|
||||||
|
|
||||||
|
- check that input device can support inputSampleFormat, or that
|
||||||
|
we have the capability to convert from outputSampleFormat to
|
||||||
|
a native format
|
||||||
|
|
||||||
|
- check that output device can support outputSampleFormat, or that
|
||||||
|
we have the capability to convert from outputSampleFormat to
|
||||||
|
a native format
|
||||||
|
|
||||||
|
- if a full duplex stream is requested, check that the combination
|
||||||
|
of input and output parameters is supported
|
||||||
|
|
||||||
|
- check that the device supports sampleRate
|
||||||
|
|
||||||
|
- alter sampleRate to a close allowable rate if possible / necessary
|
||||||
|
|
||||||
|
- validate suggestedInputLatency and suggestedOutputLatency parameters,
|
||||||
|
use default values where necessary
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* validate platform specific flags */
|
||||||
|
if( (streamFlags & paPlatformSpecificFlags) != 0 )
|
||||||
|
return paInvalidFlag; /* unexpected platform specific flag */
|
||||||
|
|
||||||
|
|
||||||
|
stream = (PaSkeletonStream*)PaUtil_AllocateMemory( sizeof(PaSkeletonStream) );
|
||||||
|
if( !stream )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( streamCallback )
|
||||||
|
{
|
||||||
|
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
|
||||||
|
&skeletonHostApi->callbackStreamInterface, streamCallback, userData );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
|
||||||
|
&skeletonHostApi->blockingStreamInterface, streamCallback, userData );
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
|
||||||
|
|
||||||
|
|
||||||
|
/* we assume a fixed host buffer size in this example, but the buffer processor
|
||||||
|
can also support bounded and unknown host buffer sizes by passing
|
||||||
|
paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
|
||||||
|
paUtilFixedHostBufferSize below. */
|
||||||
|
|
||||||
|
result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
|
||||||
|
inputChannelCount, inputSampleFormat, hostInputSampleFormat,
|
||||||
|
outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
|
||||||
|
sampleRate, streamFlags, framesPerBuffer,
|
||||||
|
framesPerHostBuffer, paUtilFixedHostBufferSize,
|
||||||
|
streamCallback, userData );
|
||||||
|
if( result != paNoError )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME: initialise the following fields with estimated or actual
|
||||||
|
values.
|
||||||
|
*/
|
||||||
|
stream->streamRepresentation.streamInfo.inputLatency =
|
||||||
|
PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);
|
||||||
|
stream->streamRepresentation.streamInfo.outputLatency =
|
||||||
|
PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);
|
||||||
|
stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME:
|
||||||
|
- additional stream setup + opening
|
||||||
|
*/
|
||||||
|
|
||||||
|
stream->framesPerHostCallback = framesPerHostBuffer;
|
||||||
|
|
||||||
|
*s = (PaStream*)stream;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if( stream )
|
||||||
|
PaUtil_FreeMemory( stream );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ExampleHostProcessingLoop() illustrates the kind of processing which may
|
||||||
|
occur in a host implementation.
|
||||||
|
|
||||||
|
*/
|
||||||
|
static void ExampleHostProcessingLoop( void *inputBuffer, void *outputBuffer, void *userData )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)userData;
|
||||||
|
PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
|
||||||
|
int callbackResult;
|
||||||
|
unsigned long framesProcessed;
|
||||||
|
|
||||||
|
PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME:
|
||||||
|
- generate timing information
|
||||||
|
- handle buffer slips
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
If you need to byte swap or shift inputBuffer to convert it into a
|
||||||
|
portaudio format, do it here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );
|
||||||
|
|
||||||
|
/*
|
||||||
|
depending on whether the host buffers are interleaved, non-interleaved
|
||||||
|
or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
|
||||||
|
PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaUtil_SetInputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
|
||||||
|
PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
|
||||||
|
0, /* first channel of inputBuffer is channel 0 */
|
||||||
|
inputBuffer,
|
||||||
|
0 ); /* 0 - use inputChannelCount passed to init buffer processor */
|
||||||
|
|
||||||
|
PaUtil_SetOutputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
|
||||||
|
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
|
||||||
|
0, /* first channel of outputBuffer is channel 0 */
|
||||||
|
outputBuffer,
|
||||||
|
0 ); /* 0 - use outputChannelCount passed to init buffer processor */
|
||||||
|
|
||||||
|
/* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
|
||||||
|
in general you would pass paContinue for normal operation, and
|
||||||
|
paComplete to drain the buffer processor's internal output buffer.
|
||||||
|
You can check whether the buffer processor's output buffer is empty
|
||||||
|
using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
|
||||||
|
*/
|
||||||
|
callbackResult = paContinue;
|
||||||
|
framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
If you need to byte swap or shift outputBuffer to convert it to
|
||||||
|
host format, do it here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
|
||||||
|
|
||||||
|
|
||||||
|
if( callbackResult == paContinue )
|
||||||
|
{
|
||||||
|
/* nothing special to do */
|
||||||
|
}
|
||||||
|
else if( callbackResult == paAbort )
|
||||||
|
{
|
||||||
|
/* IMPLEMENT ME - finish playback immediately */
|
||||||
|
|
||||||
|
/* once finished, call the finished callback */
|
||||||
|
if( stream->streamRepresentation.streamFinishedCallback != 0 )
|
||||||
|
stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* User callback has asked us to stop with paComplete or other non-zero value */
|
||||||
|
|
||||||
|
/* IMPLEMENT ME - finish playback once currently queued audio has completed */
|
||||||
|
|
||||||
|
/* once finished, call the finished callback */
|
||||||
|
if( stream->streamRepresentation.streamFinishedCallback != 0 )
|
||||||
|
stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
When CloseStream() is called, the multi-api layer ensures that
|
||||||
|
the stream has already been stopped or aborted.
|
||||||
|
*/
|
||||||
|
static PaError CloseStream( PaStream* s )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPLEMENT ME:
|
||||||
|
- additional stream closing + cleanup
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
|
||||||
|
PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
|
||||||
|
PaUtil_FreeMemory( stream );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError StartStream( PaStream *s )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior */
|
||||||
|
|
||||||
|
/* suppress unused function warning. the code in ExampleHostProcessingLoop or
|
||||||
|
something similar should be implemented to feed samples to and from the
|
||||||
|
host after StartStream() is called.
|
||||||
|
*/
|
||||||
|
(void) ExampleHostProcessingLoop;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError StopStream( PaStream *s )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError AbortStream( PaStream *s )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError IsStreamStopped( PaStream *s )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError IsStreamActive( PaStream *s )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaTime GetStreamTime( PaStream *s )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static double GetStreamCpuLoad( PaStream* s )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
As separate stream interfaces are used for blocking and callback
|
||||||
|
streams, the following functions can be guaranteed to only be called
|
||||||
|
for blocking streams.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static PaError ReadStream( PaStream* s,
|
||||||
|
void *buffer,
|
||||||
|
unsigned long frames )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) buffer;
|
||||||
|
(void) frames;
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior*/
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError WriteStream( PaStream* s,
|
||||||
|
const void *buffer,
|
||||||
|
unsigned long frames )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) buffer;
|
||||||
|
(void) frames;
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior*/
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static signed long GetStreamReadAvailable( PaStream* s )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static signed long GetStreamWriteAvailable( PaStream* s )
|
||||||
|
{
|
||||||
|
PaSkeletonStream *stream = (PaSkeletonStream*)s;
|
||||||
|
|
||||||
|
/* suppress unused variable warnings */
|
||||||
|
(void) stream;
|
||||||
|
|
||||||
|
/* IMPLEMENT ME, see portaudio.h for required behavior*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
141
portaudio-v19/pa_common/pa_stream.c
Normal file
141
portaudio-v19/pa_common/pa_stream.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 2002 Ross Bencina
|
||||||
|
*
|
||||||
|
* 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 Interface used by pa_front to virtualize functions which operate on
|
||||||
|
streams.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pa_stream.h"
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_InitializeStreamInterface( PaUtilStreamInterface *streamInterface,
|
||||||
|
PaError (*Close)( PaStream* ),
|
||||||
|
PaError (*Start)( PaStream* ),
|
||||||
|
PaError (*Stop)( PaStream* ),
|
||||||
|
PaError (*Abort)( PaStream* ),
|
||||||
|
PaError (*IsStopped)( PaStream* ),
|
||||||
|
PaError (*IsActive)( PaStream* ),
|
||||||
|
PaTime (*GetTime)( PaStream* ),
|
||||||
|
double (*GetCpuLoad)( PaStream* ),
|
||||||
|
PaError (*Read)( PaStream*, void *, unsigned long ),
|
||||||
|
PaError (*Write)( PaStream*, const void *, unsigned long ),
|
||||||
|
signed long (*GetReadAvailable)( PaStream* ),
|
||||||
|
signed long (*GetWriteAvailable)( PaStream* ) )
|
||||||
|
{
|
||||||
|
streamInterface->Close = Close;
|
||||||
|
streamInterface->Start = Start;
|
||||||
|
streamInterface->Stop = Stop;
|
||||||
|
streamInterface->Abort = Abort;
|
||||||
|
streamInterface->IsStopped = IsStopped;
|
||||||
|
streamInterface->IsActive = IsActive;
|
||||||
|
streamInterface->GetTime = GetTime;
|
||||||
|
streamInterface->GetCpuLoad = GetCpuLoad;
|
||||||
|
streamInterface->Read = Read;
|
||||||
|
streamInterface->Write = Write;
|
||||||
|
streamInterface->GetReadAvailable = GetReadAvailable;
|
||||||
|
streamInterface->GetWriteAvailable = GetWriteAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_InitializeStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation,
|
||||||
|
PaUtilStreamInterface *streamInterface,
|
||||||
|
PaStreamCallback *streamCallback,
|
||||||
|
void *userData )
|
||||||
|
{
|
||||||
|
streamRepresentation->magic = PA_STREAM_MAGIC;
|
||||||
|
streamRepresentation->nextOpenStream = 0;
|
||||||
|
streamRepresentation->streamInterface = streamInterface;
|
||||||
|
streamRepresentation->streamCallback = streamCallback;
|
||||||
|
streamRepresentation->streamFinishedCallback = 0;
|
||||||
|
|
||||||
|
streamRepresentation->userData = userData;
|
||||||
|
|
||||||
|
streamRepresentation->streamInfo.inputLatency = 0.;
|
||||||
|
streamRepresentation->streamInfo.outputLatency = 0.;
|
||||||
|
streamRepresentation->streamInfo.sampleRate = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PaUtil_TerminateStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation )
|
||||||
|
{
|
||||||
|
streamRepresentation->magic = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PaError PaUtil_DummyRead( PaStream* stream,
|
||||||
|
void *buffer,
|
||||||
|
unsigned long frames )
|
||||||
|
{
|
||||||
|
(void)stream; /* unused parameter */
|
||||||
|
(void)buffer; /* unused parameter */
|
||||||
|
(void)frames; /* unused parameter */
|
||||||
|
|
||||||
|
return paCanNotReadFromACallbackStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PaError PaUtil_DummyWrite( PaStream* stream,
|
||||||
|
const void *buffer,
|
||||||
|
unsigned long frames )
|
||||||
|
{
|
||||||
|
(void)stream; /* unused parameter */
|
||||||
|
(void)buffer; /* unused parameter */
|
||||||
|
(void)frames; /* unused parameter */
|
||||||
|
|
||||||
|
return paCanNotWriteToACallbackStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
signed long PaUtil_DummyGetReadAvailable( PaStream* stream )
|
||||||
|
{
|
||||||
|
(void)stream; /* unused parameter */
|
||||||
|
|
||||||
|
return paCanNotReadFromACallbackStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
signed long PaUtil_DummyGetWriteAvailable( PaStream* stream )
|
||||||
|
{
|
||||||
|
(void)stream; /* unused parameter */
|
||||||
|
|
||||||
|
return paCanNotWriteToACallbackStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double PaUtil_DummyGetCpuLoad( PaStream* stream )
|
||||||
|
{
|
||||||
|
(void)stream; /* unused parameter */
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
196
portaudio-v19/pa_common/pa_stream.h
Normal file
196
portaudio-v19/pa_common/pa_stream.h
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#ifndef PA_STREAM_H
|
||||||
|
#define PA_STREAM_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library
|
||||||
|
* stream interface
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
@brief Interface used by pa_front to virtualize functions which operate on
|
||||||
|
streams.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#define PA_STREAM_MAGIC (0x18273645)
|
||||||
|
|
||||||
|
|
||||||
|
/** A structure representing an (abstract) interface to a host API. Contains
|
||||||
|
pointers to functions which implement the interface.
|
||||||
|
|
||||||
|
All PaStreamInterface functions are guaranteed to be called with a non-null,
|
||||||
|
valid stream parameter.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
PaError (*Close)( PaStream* stream );
|
||||||
|
PaError (*Start)( PaStream *stream );
|
||||||
|
PaError (*Stop)( PaStream *stream );
|
||||||
|
PaError (*Abort)( PaStream *stream );
|
||||||
|
PaError (*IsStopped)( PaStream *stream );
|
||||||
|
PaError (*IsActive)( PaStream *stream );
|
||||||
|
PaTime (*GetTime)( PaStream *stream );
|
||||||
|
double (*GetCpuLoad)( PaStream* stream );
|
||||||
|
PaError (*Read)( PaStream* stream, void *buffer, unsigned long frames );
|
||||||
|
PaError (*Write)( PaStream* stream, const void *buffer, unsigned long frames );
|
||||||
|
signed long (*GetReadAvailable)( PaStream* stream );
|
||||||
|
signed long (*GetWriteAvailable)( PaStream* stream );
|
||||||
|
} PaUtilStreamInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/** Initialize the fields of a PaUtilStreamInterface structure.
|
||||||
|
*/
|
||||||
|
void PaUtil_InitializeStreamInterface( PaUtilStreamInterface *streamInterface,
|
||||||
|
PaError (*Close)( PaStream* ),
|
||||||
|
PaError (*Start)( PaStream* ),
|
||||||
|
PaError (*Stop)( PaStream* ),
|
||||||
|
PaError (*Abort)( PaStream* ),
|
||||||
|
PaError (*IsStopped)( PaStream* ),
|
||||||
|
PaError (*IsActive)( PaStream* ),
|
||||||
|
PaTime (*GetTime)( PaStream* ),
|
||||||
|
double (*GetCpuLoad)( PaStream* ),
|
||||||
|
PaError (*Read)( PaStream* stream, void *buffer, unsigned long frames ),
|
||||||
|
PaError (*Write)( PaStream* stream, const void *buffer, unsigned long frames ),
|
||||||
|
signed long (*GetReadAvailable)( PaStream* stream ),
|
||||||
|
signed long (*GetWriteAvailable)( PaStream* stream ) );
|
||||||
|
|
||||||
|
|
||||||
|
/** Dummy Read function for use in interfaces to a callback based streams.
|
||||||
|
Pass to the Read parameter of PaUtil_InitializeStreamInterface.
|
||||||
|
@return An error code indicating that the function has no effect
|
||||||
|
because the stream is a callback stream.
|
||||||
|
*/
|
||||||
|
PaError PaUtil_DummyRead( PaStream* stream,
|
||||||
|
void *buffer,
|
||||||
|
unsigned long frames );
|
||||||
|
|
||||||
|
|
||||||
|
/** Dummy Write function for use in an interfaces to callback based streams.
|
||||||
|
Pass to the Write parameter of PaUtil_InitializeStreamInterface.
|
||||||
|
@return An error code indicating that the function has no effect
|
||||||
|
because the stream is a callback stream.
|
||||||
|
*/
|
||||||
|
PaError PaUtil_DummyWrite( PaStream* stream,
|
||||||
|
const void *buffer,
|
||||||
|
unsigned long frames );
|
||||||
|
|
||||||
|
|
||||||
|
/** Dummy GetReadAvailable function for use in interfaces to callback based
|
||||||
|
streams. Pass to the GetReadAvailable parameter of PaUtil_InitializeStreamInterface.
|
||||||
|
@return An error code indicating that the function has no effect
|
||||||
|
because the stream is a callback stream.
|
||||||
|
*/
|
||||||
|
signed long PaUtil_DummyGetReadAvailable( PaStream* stream );
|
||||||
|
|
||||||
|
|
||||||
|
/** Dummy GetWriteAvailable function for use in interfaces to callback based
|
||||||
|
streams. Pass to the GetWriteAvailable parameter of PaUtil_InitializeStreamInterface.
|
||||||
|
@return An error code indicating that the function has no effect
|
||||||
|
because the stream is a callback stream.
|
||||||
|
*/
|
||||||
|
signed long PaUtil_DummyGetWriteAvailable( PaStream* stream );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Dummy GetCpuLoad function for use in an interface to a read/write stream.
|
||||||
|
Pass to the GetCpuLoad parameter of PaUtil_InitializeStreamInterface.
|
||||||
|
@return Returns 0.
|
||||||
|
*/
|
||||||
|
double PaUtil_DummyGetCpuLoad( PaStream* stream );
|
||||||
|
|
||||||
|
|
||||||
|
/** Non host specific data for a stream. This data is used by pa_front to
|
||||||
|
forward to the appropriate functions in the streamInterface structure.
|
||||||
|
*/
|
||||||
|
typedef struct PaUtilStreamRepresentation {
|
||||||
|
unsigned long magic; /**< set to PA_STREAM_MAGIC */
|
||||||
|
struct PaUtilStreamRepresentation *nextOpenStream; /**< field used by multi-api code */
|
||||||
|
PaUtilStreamInterface *streamInterface;
|
||||||
|
PaStreamCallback *streamCallback;
|
||||||
|
PaStreamFinishedCallback *streamFinishedCallback;
|
||||||
|
void *userData;
|
||||||
|
PaStreamInfo streamInfo;
|
||||||
|
} PaUtilStreamRepresentation;
|
||||||
|
|
||||||
|
|
||||||
|
/** Initialize a PaUtilStreamRepresentation structure.
|
||||||
|
|
||||||
|
@see PaUtil_InitializeStreamRepresentation
|
||||||
|
*/
|
||||||
|
void PaUtil_InitializeStreamRepresentation(
|
||||||
|
PaUtilStreamRepresentation *streamRepresentation,
|
||||||
|
PaUtilStreamInterface *streamInterface,
|
||||||
|
PaStreamCallback *streamCallback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
/** Clean up a PaUtilStreamRepresentation structure previously initialized
|
||||||
|
by a call to PaUtil_InitializeStreamRepresentation.
|
||||||
|
|
||||||
|
@see PaUtil_InitializeStreamRepresentation
|
||||||
|
*/
|
||||||
|
void PaUtil_TerminateStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation );
|
||||||
|
|
||||||
|
|
||||||
|
/** Check that the stream pointer is valid.
|
||||||
|
|
||||||
|
@return Returns paNoError if the stream pointer appears to be OK, otherwise
|
||||||
|
returns an error indicating the cause of failure.
|
||||||
|
*/
|
||||||
|
PaError PaUtil_ValidateStreamPointer( PaStream *stream );
|
||||||
|
|
||||||
|
|
||||||
|
/** Cast an opaque stream pointer into a pointer to a PaUtilStreamRepresentation.
|
||||||
|
|
||||||
|
@see PaUtilStreamRepresentation
|
||||||
|
*/
|
||||||
|
#define PA_STREAM_REP( stream )\
|
||||||
|
((PaUtilStreamRepresentation*) (stream) )
|
||||||
|
|
||||||
|
|
||||||
|
/** Cast an opaque stream pointer into a pointer to a PaUtilStreamInterface.
|
||||||
|
|
||||||
|
@see PaUtilStreamRepresentation, PaUtilStreamInterface
|
||||||
|
*/
|
||||||
|
#define PA_STREAM_INTERFACE( stream )\
|
||||||
|
PA_STREAM_REP( (stream) )->streamInterface
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_STREAM_H */
|
||||||
88
portaudio-v19/pa_common/pa_trace.c
Normal file
88
portaudio-v19/pa_common/pa_trace.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library Trace Facility
|
||||||
|
* Store trace information in real-time for later printing.
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2000 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 Event trace mechanism for debugging.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "pa_trace.h"
|
||||||
|
|
||||||
|
#if PA_TRACE_REALTIME_EVENTS
|
||||||
|
|
||||||
|
static char *traceTextArray[PA_MAX_TRACE_RECORDS];
|
||||||
|
static int traceIntArray[PA_MAX_TRACE_RECORDS];
|
||||||
|
static int traceIndex = 0;
|
||||||
|
static int traceBlock = 0;
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
void PaUtil_ResetTraceMessages()
|
||||||
|
{
|
||||||
|
traceIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
void PaUtil_DumpTraceMessages()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int messageCount = (traceIndex < PA_MAX_TRACE_RECORDS) ? traceIndex : PA_MAX_TRACE_RECORDS;
|
||||||
|
|
||||||
|
printf("DumpTraceMessages: traceIndex = %d\n", traceIndex );
|
||||||
|
for( i=0; i<messageCount; i++ )
|
||||||
|
{
|
||||||
|
printf("%3d: %s = 0x%08X\n",
|
||||||
|
i, traceTextArray[i], traceIntArray[i] );
|
||||||
|
}
|
||||||
|
PaUtil_ResetTraceMessages();
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
void PaUtil_AddTraceMessage( const char *msg, int data )
|
||||||
|
{
|
||||||
|
if( (traceIndex == PA_MAX_TRACE_RECORDS) && (traceBlock == 0) )
|
||||||
|
{
|
||||||
|
traceBlock = 1;
|
||||||
|
/* PaUtil_DumpTraceMessages(); */
|
||||||
|
}
|
||||||
|
else if( traceIndex < PA_MAX_TRACE_RECORDS )
|
||||||
|
{
|
||||||
|
traceTextArray[traceIndex] = msg;
|
||||||
|
traceIntArray[traceIndex] = data;
|
||||||
|
traceIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TRACE_REALTIME_EVENTS */
|
||||||
70
portaudio-v19/pa_common/pa_trace.h
Normal file
70
portaudio-v19/pa_common/pa_trace.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef PA_TRACE_H
|
||||||
|
#define PA_TRACE_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library Trace Facility
|
||||||
|
* Store trace information in real-time for later printing.
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2000 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 Event trace mechanism for debugging.
|
||||||
|
|
||||||
|
Allows data to be written to the buffer at interrupt time and dumped later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define PA_TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */
|
||||||
|
#define PA_MAX_TRACE_RECORDS (2048)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#if PA_TRACE_REALTIME_EVENTS
|
||||||
|
|
||||||
|
void PaUtil_ResetTraceMessages();
|
||||||
|
void PaUtil_AddTraceMessage( const char *msg, int data );
|
||||||
|
void PaUtil_DumpTraceMessages();
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define PaUtil_ResetTraceMessages() /* noop */
|
||||||
|
#define PaUtil_AddTraceMessage(msg,data) /* noop */
|
||||||
|
#define PaUtil_DumpTraceMessages() /* noop */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* PA_TRACE_H */
|
||||||
65
portaudio-v19/pa_common/pa_types.h
Normal file
65
portaudio-v19/pa_common/pa_types.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef PA_TYPES_H
|
||||||
|
#define PA_TYPES_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
SIZEOF_SHORT, SIZEOF_INT and SIZEOF_LONG are set by the configure script
|
||||||
|
when it is used. Otherwise we default to the common 32 bit values, if your
|
||||||
|
platform doesn't use configure, and doesn't use the default values below
|
||||||
|
you will need to explicitly define these symbols in your make file.
|
||||||
|
|
||||||
|
A PA_VALIDATE_SIZES macro is provided to assert that the values set in this
|
||||||
|
file are correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SIZEOF_SHORT
|
||||||
|
#define SIZEOF_SHORT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIZEOF_INT
|
||||||
|
#define SIZEOF_INT 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIZEOF_LONG
|
||||||
|
#define SIZEOF_LONG 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if SIZEOF_SHORT == 2
|
||||||
|
typedef signed short PaInt16;
|
||||||
|
typedef unsigned short PaUint16;
|
||||||
|
#elif SIZEOF_INT == 2
|
||||||
|
typedef signed int PaInt16;
|
||||||
|
typedef unsigned int PaUint16;
|
||||||
|
#else
|
||||||
|
#error pa_types.h was unable to determine which type to use for 16bit integers on the target platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SIZEOF_SHORT == 4
|
||||||
|
typedef signed short PaInt32;
|
||||||
|
typedef unsigned short PaUint32;
|
||||||
|
#elif SIZEOF_INT == 4
|
||||||
|
typedef signed int PaInt32;
|
||||||
|
typedef unsigned int PaUint32;
|
||||||
|
#elif SIZEOF_LONG == 4
|
||||||
|
typedef signed long PaInt32;
|
||||||
|
typedef unsigned long PaUint32;
|
||||||
|
#else
|
||||||
|
#error pa_types.h was unable to determine which type to use for 32bit integers on the target platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* PA_VALIDATE_TYPE_SIZES compares the size of the integer types at runtime to
|
||||||
|
ensure that PortAudio was configured correctly, and raises an assertion if
|
||||||
|
they don't match the expected values. <assert.h> must be included in the
|
||||||
|
context in which this macro is used.
|
||||||
|
*/
|
||||||
|
#define PA_VALIDATE_TYPE_SIZES \
|
||||||
|
{ \
|
||||||
|
assert( "PortAudio: type sizes are not correct in pa_types.h" && sizeof( PaUint16 ) == 2 ); \
|
||||||
|
assert( "PortAudio: type sizes are not correct in pa_types.h" && sizeof( PaInt16 ) == 2 ); \
|
||||||
|
assert( "PortAudio: type sizes are not correct in pa_types.h" && sizeof( PaUint32 ) == 4 ); \
|
||||||
|
assert( "PortAudio: type sizes are not correct in pa_types.h" && sizeof( PaInt32 ) == 4 ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PA_TYPES_H */
|
||||||
167
portaudio-v19/pa_common/pa_util.h
Normal file
167
portaudio-v19/pa_common/pa_util.h
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#ifndef PA_UTIL_H
|
||||||
|
#define PA_UTIL_H
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* Portable Audio I/O Library implementation utilities header
|
||||||
|
* common implementation utilities and interfaces
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
@brief Prototypes for utility functions used by PortAudio implementations.
|
||||||
|
|
||||||
|
@todo Document and adhere to the alignment guarantees provided by
|
||||||
|
PaUtil_AllocateMemory().
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
struct PaUtilHostApiRepresentation;
|
||||||
|
|
||||||
|
|
||||||
|
/** Retrieve a specific host API representation. This function can be used
|
||||||
|
by implementations to retrieve a pointer to their representation in
|
||||||
|
host api specific extension functions which aren't passed a rep pointer
|
||||||
|
by pa_front.c.
|
||||||
|
|
||||||
|
@param hostApi A pointer to a host API represenation pointer. Apon success
|
||||||
|
this will receive the requested representation pointer.
|
||||||
|
|
||||||
|
@param type A valid host API type identifier.
|
||||||
|
|
||||||
|
@returns An error code. If the result is PaNoError then a pointer to the
|
||||||
|
requested host API representation will be stored in *hostApi. If the host API
|
||||||
|
specified by type is not found, this function returns paHostApiNotFound.
|
||||||
|
*/
|
||||||
|
PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
|
||||||
|
PaHostApiTypeId type );
|
||||||
|
|
||||||
|
|
||||||
|
/** Convert a PortAudio device index into a host API specific device index.
|
||||||
|
@param hostApiDevice Pointer to a device index, on success this will recieve the
|
||||||
|
converted device index value.
|
||||||
|
@param device The PortAudio device index to convert.
|
||||||
|
@param hostApi The host api which the index should be converted for.
|
||||||
|
|
||||||
|
@returns On success returns PaNoError and places the converted index in the
|
||||||
|
hostApiDevice parameter.
|
||||||
|
*/
|
||||||
|
PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
|
||||||
|
PaDeviceIndex *hostApiDevice, PaDeviceIndex device,
|
||||||
|
struct PaUtilHostApiRepresentation *hostApi );
|
||||||
|
|
||||||
|
|
||||||
|
/** Set the host error information returned by Pa_GetLastHostErrorInfo. This
|
||||||
|
function and the paUnanticipatedHostError error code should be used as a
|
||||||
|
last resort. Implementors should use existing PA error codes where possible,
|
||||||
|
or nominate new ones. Note that at it is always better to use
|
||||||
|
PaUtil_SetLastHostErrorInfo() and paUnanticipatedHostError than to return an
|
||||||
|
ambiguous or inaccurate PaError code.
|
||||||
|
|
||||||
|
@param hostApiType The host API which encountered the error (ie of the caller)
|
||||||
|
|
||||||
|
@param errorCode The error code returned by the native API function.
|
||||||
|
|
||||||
|
@param errorText A string describing the error. PaUtil_SetLastHostErrorInfo
|
||||||
|
makes a copy of the string, so it is not necessary for the pointer to remain
|
||||||
|
valid after the call to PaUtil_SetLastHostErrorInfo() returns.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
|
||||||
|
const char *errorText );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** PA_DEBUG() provides a simple debug message printing facility. The macro
|
||||||
|
passes it's argument to a printf-like function called PaUtil_DebugPrint()
|
||||||
|
which prints to stderr and always flushes the stream after printing.
|
||||||
|
Because preprocessor macros cannot directly accept variable length argument
|
||||||
|
lists, calls to the macro must include an additional set of parenthesis, eg:
|
||||||
|
PA_DEBUG(("errorno: %d", 1001 ));
|
||||||
|
*/
|
||||||
|
|
||||||
|
void PaUtil_DebugPrint( const char *format, ... );
|
||||||
|
|
||||||
|
#ifdef PA_ENABLE_DEBUG_OUTPUT
|
||||||
|
#define PA_DEBUG(x) PaUtil_DebugPrint x ;
|
||||||
|
#else
|
||||||
|
#define PA_DEBUG(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* the following functions are implemented in a platform platform specific
|
||||||
|
.c file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Allocate size bytes, guaranteed to be aligned to a FIXME byte boundary */
|
||||||
|
void *PaUtil_AllocateMemory( long size );
|
||||||
|
|
||||||
|
|
||||||
|
/** Realease block if non-NULL. block may be NULL */
|
||||||
|
void PaUtil_FreeMemory( void *block );
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the number of currently allocated blocks. This function can be
|
||||||
|
used for detecting memory leaks.
|
||||||
|
|
||||||
|
@note Allocations will only be tracked if PA_TRACK_MEMORY is #defined. If
|
||||||
|
it isn't, this function will always return 0.
|
||||||
|
*/
|
||||||
|
int PaUtil_CountCurrentlyAllocatedBlocks( void );
|
||||||
|
|
||||||
|
|
||||||
|
/** Initialize the clock used by PaUtil_GetTime(). Call this before calling
|
||||||
|
PaUtil_GetTime.
|
||||||
|
|
||||||
|
@see PaUtil_GetTime
|
||||||
|
*/
|
||||||
|
void PaUtil_InitializeClock( void );
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the system time in seconds. Used to implement CPU load functions
|
||||||
|
|
||||||
|
@see PaUtil_InitializeClock
|
||||||
|
*/
|
||||||
|
double PaUtil_GetTime( void );
|
||||||
|
|
||||||
|
|
||||||
|
/* void Pa_Sleep( long msec ); must also be implemented in per-platform .c file */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PA_UTIL_H */
|
||||||
1124
portaudio-v19/pa_common/portaudio.h
Normal file
1124
portaudio-v19/pa_common/portaudio.h
Normal file
File diff suppressed because it is too large
Load Diff
184
portaudio-v19/pa_dll_switch/PaDllEntry.h
Normal file
184
portaudio-v19/pa_dll_switch/PaDllEntry.h
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* PortAudio DLL Header File
|
||||||
|
* Latest version available at: 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// changed by zplane.developement in order to generate a DLL
|
||||||
|
|
||||||
|
#ifndef __PADLLENTRY_HEADER_INCLUDED__
|
||||||
|
|
||||||
|
#define __PADLLENTRY_HEADER_INCLUDED__
|
||||||
|
|
||||||
|
typedef int PaError;
|
||||||
|
typedef enum {
|
||||||
|
paNoError = 0,
|
||||||
|
|
||||||
|
paHostError = -10000,
|
||||||
|
paInvalidChannelCount,
|
||||||
|
paInvalidSampleRate,
|
||||||
|
paInvalidDeviceId,
|
||||||
|
paInvalidFlag,
|
||||||
|
paSampleFormatNotSupported,
|
||||||
|
paBadIODeviceCombination,
|
||||||
|
paInsufficientMemory,
|
||||||
|
paBufferTooBig,
|
||||||
|
paBufferTooSmall,
|
||||||
|
paNullCallback,
|
||||||
|
paBadStreamPtr,
|
||||||
|
paTimedOut,
|
||||||
|
paInternalError
|
||||||
|
} PaErrorNum;
|
||||||
|
|
||||||
|
typedef unsigned long PaSampleFormat;
|
||||||
|
#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/
|
||||||
|
#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/
|
||||||
|
#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/
|
||||||
|
#define paInt24 ((PaSampleFormat) (1<<3))
|
||||||
|
#define paPackedInt24 ((PaSampleFormat) (1<<4))
|
||||||
|
#define paInt8 ((PaSampleFormat) (1<<5))
|
||||||
|
#define paUInt8 ((PaSampleFormat) (1<<6)) /* unsigned 8 bit, 128 is "ground" */
|
||||||
|
#define paCustomFormat ((PaSampleFormat) (1<<16))
|
||||||
|
|
||||||
|
|
||||||
|
typedef int PaDeviceID;
|
||||||
|
#define paNoDevice -1
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int structVersion;
|
||||||
|
const char *name;
|
||||||
|
int maxInputChannels;
|
||||||
|
int maxOutputChannels;
|
||||||
|
/* Number of discrete rates, or -1 if range supported. */
|
||||||
|
int numSampleRates;
|
||||||
|
/* Array of supported sample rates, or {min,max} if range supported. */
|
||||||
|
const double *sampleRates;
|
||||||
|
PaSampleFormat nativeSampleFormats;
|
||||||
|
}
|
||||||
|
PaDeviceInfo;
|
||||||
|
|
||||||
|
|
||||||
|
typedef double PaTimestamp;
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (PortAudioCallback)(
|
||||||
|
void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaTimestamp outTime, void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
#define paNoFlag (0)
|
||||||
|
#define paClipOff (1<<0) /* disable default clipping of out of range samples */
|
||||||
|
#define paDitherOff (1<<1) /* disable default dithering */
|
||||||
|
#define paPlatformSpecificFlags (0x00010000)
|
||||||
|
typedef unsigned long PaStreamFlags;
|
||||||
|
|
||||||
|
typedef void PortAudioStream;
|
||||||
|
#define PaStream PortAudioStream
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_Initialize)( void );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_Terminate)( void );
|
||||||
|
|
||||||
|
|
||||||
|
extern long (__cdecl* Pa_GetHostError)( void );
|
||||||
|
|
||||||
|
|
||||||
|
extern const char* (__cdecl* Pa_GetErrorText)( PaError );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern int (__cdecl* Pa_CountDevices)(void);
|
||||||
|
|
||||||
|
extern PaDeviceID (__cdecl* Pa_GetDefaultInputDeviceID)( void );
|
||||||
|
|
||||||
|
extern PaDeviceID (__cdecl* Pa_GetDefaultOutputDeviceID)( void );
|
||||||
|
|
||||||
|
|
||||||
|
extern const PaDeviceInfo* (__cdecl* Pa_GetDeviceInfo)( PaDeviceID);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_OpenStream)(
|
||||||
|
PortAudioStream ** ,
|
||||||
|
PaDeviceID ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
void *,
|
||||||
|
PaDeviceID ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
void *,
|
||||||
|
double ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
PortAudioCallback *,
|
||||||
|
void * );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_OpenDefaultStream)( PortAudioStream** stream,
|
||||||
|
int numInputChannels,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat sampleFormat,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_CloseStream)( PortAudioStream* );
|
||||||
|
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_StartStream)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_StopStream)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_AbortStream)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_StreamActive)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
extern PaTimestamp (__cdecl* Pa_StreamTime)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
extern double (__cdecl* Pa_GetCPULoad)( PortAudioStream* stream );
|
||||||
|
|
||||||
|
extern int (__cdecl* Pa_GetMinNumBuffers)( int framesPerBuffer, double sampleRate );
|
||||||
|
|
||||||
|
extern void (__cdecl* Pa_Sleep)( long msec );
|
||||||
|
|
||||||
|
extern PaError (__cdecl* Pa_GetSampleSize)( PaSampleFormat format );
|
||||||
|
|
||||||
|
#endif // __PADLLENTRY_HEADER_INCLUDED__
|
||||||
|
|
||||||
BIN
portaudio-v19/pa_dll_switch/letter_from_tim_010817.txt
Normal file
BIN
portaudio-v19/pa_dll_switch/letter_from_tim_010817.txt
Normal file
Binary file not shown.
203
portaudio-v19/pa_dll_switch/loadPA_DLL.cpp
Normal file
203
portaudio-v19/pa_dll_switch/loadPA_DLL.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
HINSTANCE pPaDll;
|
||||||
|
|
||||||
|
/*
|
||||||
|
the function pointers to the PortAudio DLLs
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_Initialize)( void );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_Terminate)( void );
|
||||||
|
|
||||||
|
|
||||||
|
long (__cdecl* Pa_GetHostError)( void );
|
||||||
|
|
||||||
|
|
||||||
|
const char* (__cdecl* Pa_GetErrorText)( PaError );
|
||||||
|
|
||||||
|
|
||||||
|
int (__cdecl* Pa_CountDevices)(void);
|
||||||
|
|
||||||
|
PaDeviceID (__cdecl* Pa_GetDefaultInputDeviceID)( void );
|
||||||
|
|
||||||
|
PaDeviceID (__cdecl* Pa_GetDefaultOutputDeviceID)( void );
|
||||||
|
|
||||||
|
|
||||||
|
const PaDeviceInfo* (__cdecl* Pa_GetDeviceInfo)( PaDeviceID);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_OpenStream)(
|
||||||
|
PortAudioStream ** ,
|
||||||
|
PaDeviceID ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
void *,
|
||||||
|
PaDeviceID ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
void *,
|
||||||
|
double ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
PortAudioCallback *,
|
||||||
|
void * );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_OpenDefaultStream)( PortAudioStream** stream,
|
||||||
|
int numInputChannels,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat sampleFormat,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_CloseStream)( PortAudioStream* );
|
||||||
|
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_StartStream)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_StopStream)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_AbortStream)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_StreamActive)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
PaTimestamp (__cdecl* Pa_StreamTime)( PortAudioStream *stream );
|
||||||
|
|
||||||
|
double (__cdecl* Pa_GetCPULoad)( PortAudioStream* stream );
|
||||||
|
|
||||||
|
int (__cdecl* Pa_GetMinNumBuffers)( int framesPerBuffer, double sampleRate );
|
||||||
|
|
||||||
|
void (__cdecl* Pa_Sleep)( long msec );
|
||||||
|
|
||||||
|
PaError (__cdecl* Pa_GetSampleSize)( PaSampleFormat format );
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
ZERROR AudioEngine::DirectXSupport(ZBOOL bSupDX)
|
||||||
|
{
|
||||||
|
if (bSupDX)
|
||||||
|
if (CheckForDirectXSupport())
|
||||||
|
bSupportDirectX = _TRUE;
|
||||||
|
else
|
||||||
|
return _NO_SOUND;
|
||||||
|
else
|
||||||
|
bSupportDirectX = _FALSE;
|
||||||
|
return _NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ZBOOL AudioEngine::CheckForDirectXSupport()
|
||||||
|
{
|
||||||
|
HMODULE pTestDXLib;
|
||||||
|
FARPROC pFunctionality;
|
||||||
|
|
||||||
|
pTestDXLib=LoadLibrary("DSOUND");
|
||||||
|
if (pTestDXLib!=NULL) // check if there is a DirectSound
|
||||||
|
{
|
||||||
|
pFunctionality = GetProcAddress(pTestDXLib, (char*) 7);
|
||||||
|
if (pFunctionality!=NULL)
|
||||||
|
{
|
||||||
|
FreeLibrary(pTestDXLib);
|
||||||
|
return _TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FreeLibrary(pTestDXLib);
|
||||||
|
return _FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return _FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZERROR AudioEngine::LoadPALib()
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if (bSupportDirectX)
|
||||||
|
pPaDll = LoadLibrary("PA_DXD");
|
||||||
|
else
|
||||||
|
pPaDll = LoadLibrary("PA_MMED");
|
||||||
|
#else
|
||||||
|
if (bSupportDirectX)
|
||||||
|
pPaDll = LoadLibrary("PA_DX");
|
||||||
|
else
|
||||||
|
pPaDll = LoadLibrary("PA_MME");
|
||||||
|
#endif
|
||||||
|
if (pPaDll!=NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
Pa_Initialize = (int (__cdecl*)(void))GetProcAddress(pPaDll,"Pa_Initialize");
|
||||||
|
Pa_Terminate = (int (__cdecl*)(void))GetProcAddress(pPaDll,"Pa_Terminate");
|
||||||
|
Pa_GetHostError = (long (__cdecl* )( void )) GetProcAddress(pPaDll,"Pa_GetHostError");
|
||||||
|
Pa_GetErrorText = (const char* (__cdecl* )( PaError )) GetProcAddress(pPaDll,"Pa_GetErrorText");
|
||||||
|
Pa_CountDevices = (int (__cdecl*)(void))GetProcAddress(pPaDll,"Pa_CountDevices");
|
||||||
|
Pa_GetDefaultInputDeviceID = (int (__cdecl*)(void))GetProcAddress(pPaDll,"Pa_GetDefaultInputDeviceID");
|
||||||
|
Pa_GetDefaultOutputDeviceID = (int (__cdecl*)(void))GetProcAddress(pPaDll,"Pa_GetDefaultOutputDeviceID");
|
||||||
|
Pa_GetDeviceInfo = (const PaDeviceInfo* (__cdecl* )( PaDeviceID)) GetProcAddress(pPaDll,"Pa_GetDeviceInfo");
|
||||||
|
Pa_OpenStream = ( PaError (__cdecl* )(
|
||||||
|
PortAudioStream ** ,
|
||||||
|
PaDeviceID ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
void *,
|
||||||
|
PaDeviceID ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
void *,
|
||||||
|
double ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
PortAudioCallback *,
|
||||||
|
void * )) GetProcAddress(pPaDll,"Pa_OpenStream");
|
||||||
|
|
||||||
|
Pa_OpenDefaultStream = (PaError (__cdecl* )( PortAudioStream** ,
|
||||||
|
int ,
|
||||||
|
int ,
|
||||||
|
PaSampleFormat ,
|
||||||
|
double ,
|
||||||
|
unsigned long ,
|
||||||
|
unsigned long ,
|
||||||
|
PortAudioCallback *,
|
||||||
|
void * )) GetProcAddress(pPaDll,"Pa_OpenDefaultStream");
|
||||||
|
Pa_CloseStream = (PaError (__cdecl* )( PortAudioStream* )) GetProcAddress(pPaDll,"Pa_CloseStream");
|
||||||
|
Pa_StartStream = (PaError (__cdecl* )( PortAudioStream* )) GetProcAddress(pPaDll,"Pa_StartStream");
|
||||||
|
Pa_StopStream = (PaError (__cdecl* )( PortAudioStream* ))GetProcAddress(pPaDll,"Pa_StopStream");
|
||||||
|
Pa_AbortStream = (PaError (__cdecl* )( PortAudioStream* )) GetProcAddress(pPaDll,"Pa_AbortStream");
|
||||||
|
Pa_StreamActive = (PaError (__cdecl* )( PortAudioStream* )) GetProcAddress(pPaDll,"Pa_StreamActive");
|
||||||
|
Pa_StreamTime = (PaTimestamp (__cdecl* )( PortAudioStream *))GetProcAddress(pPaDll,"Pa_StreamTime");
|
||||||
|
Pa_GetCPULoad = (double (__cdecl* )( PortAudioStream* ))GetProcAddress(pPaDll,"Pa_GetCPULoad");
|
||||||
|
Pa_GetMinNumBuffers = (int (__cdecl* )( int , double )) GetProcAddress(pPaDll,"Pa_GetMinNumBuffers");
|
||||||
|
Pa_Sleep = (void (__cdecl* )( long )) GetProcAddress(pPaDll,"Pa_Sleep");
|
||||||
|
Pa_GetSampleSize = (PaError (__cdecl* )( PaSampleFormat )) GetProcAddress(pPaDll,"Pa_GetSampleSize");
|
||||||
|
|
||||||
|
return _NO_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return _DLL_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZERROR AudioEngine::UnLoadPALib()
|
||||||
|
{
|
||||||
|
if (pPaDll!=NULL)
|
||||||
|
FreeLibrary(pPaDll);
|
||||||
|
return _NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
827
portaudio-v19/pa_dll_switch/pa_lib.c
Normal file
827
portaudio-v19/pa_dll_switch/pa_lib.c
Normal file
@ -0,0 +1,827 @@
|
|||||||
|
/*
|
||||||
|
* Portable Audio I/O Library
|
||||||
|
* Host Independant Layer
|
||||||
|
*
|
||||||
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
|
* Copyright (c) 1999-2000 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Modification History:
|
||||||
|
PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* PLB20010422 - "memory.h" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef __MWERKS__
|
||||||
|
#include <memory.h>
|
||||||
|
#endif /* __MWERKS__ */
|
||||||
|
#else /* !_WIN32 */
|
||||||
|
#include <memory.h>
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
#include "pa_host.h"
|
||||||
|
#include "pa_trace.h"
|
||||||
|
|
||||||
|
/* The reason we might NOT want to validate the rate before opening the stream
|
||||||
|
* is because many DirectSound drivers lie about the rates they actually support.
|
||||||
|
*/
|
||||||
|
#define PA_VALIDATE_RATE (0) /* If true validate sample rate against driver info. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
O- maybe not allocate past_InputBuffer and past_OutputBuffer if not needed for conversion
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (0)
|
||||||
|
#define TRUE (!FALSE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PRINT(x) { printf x; fflush(stdout); }
|
||||||
|
#define ERR_RPT(x) PRINT(x)
|
||||||
|
#define DBUG(x) /* PRINT(x) */
|
||||||
|
#define DBUGX(x) /* PRINT(x) */
|
||||||
|
|
||||||
|
static int gInitCount = 0; /* Count number of times Pa_Initialize() called to allow nesting and overlapping. */
|
||||||
|
|
||||||
|
static PaError Pa_KillStream( PortAudioStream *stream, int abort );
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate )
|
||||||
|
{
|
||||||
|
double err, minErr = allowableError;
|
||||||
|
int i, bestFit = -1;
|
||||||
|
|
||||||
|
for( i=0; i<numRates; i++ )
|
||||||
|
{
|
||||||
|
err = fabs( frameRate - rateTable[i] );
|
||||||
|
if( err < minErr )
|
||||||
|
{
|
||||||
|
minErr = err;
|
||||||
|
bestFit = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestFit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
** Make sure sample rate is legal and also convert to enumeration for driver.
|
||||||
|
*/
|
||||||
|
PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate,
|
||||||
|
double *closestFrameRatePtr )
|
||||||
|
{
|
||||||
|
long bestRateIndex;
|
||||||
|
const PaDeviceInfo *pdi;
|
||||||
|
pdi = Pa_GetDeviceInfo( id );
|
||||||
|
if( pdi == NULL ) return paInvalidDeviceId;
|
||||||
|
|
||||||
|
if( pdi->numSampleRates == -1 )
|
||||||
|
{
|
||||||
|
/* Is it out of range? */
|
||||||
|
if( (requestedFrameRate < pdi->sampleRates[0]) ||
|
||||||
|
(requestedFrameRate > pdi->sampleRates[1]) )
|
||||||
|
{
|
||||||
|
return paInvalidSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
*closestFrameRatePtr = requestedFrameRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bestRateIndex = PaHost_FindClosestTableEntry( 1.0, pdi->sampleRates, pdi->numSampleRates, requestedFrameRate );
|
||||||
|
if( bestRateIndex < 0 ) return paInvalidSampleRate;
|
||||||
|
*closestFrameRatePtr = pdi->sampleRates[bestRateIndex];
|
||||||
|
}
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_OpenStream(
|
||||||
|
PortAudioStream** streamPtrPtr,
|
||||||
|
PaDeviceID inputDeviceID,
|
||||||
|
int numInputChannels,
|
||||||
|
PaSampleFormat inputSampleFormat,
|
||||||
|
void *inputDriverInfo,
|
||||||
|
PaDeviceID outputDeviceID,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat outputSampleFormat,
|
||||||
|
void *outputDriverInfo,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
unsigned long streamFlags,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData )
|
||||||
|
{
|
||||||
|
internalPortAudioStream *past = NULL;
|
||||||
|
PaError result = paNoError;
|
||||||
|
int bitsPerInputSample;
|
||||||
|
int bitsPerOutputSample;
|
||||||
|
/* Print passed parameters. */
|
||||||
|
DBUG(("Pa_OpenStream( %p, %d, %d, %d, %p, /* input */ \n",
|
||||||
|
streamPtrPtr, inputDeviceID, numInputChannels,
|
||||||
|
inputSampleFormat, inputDriverInfo ));
|
||||||
|
DBUG((" %d, %d, %d, %p, /* output */\n",
|
||||||
|
outputDeviceID, numOutputChannels,
|
||||||
|
outputSampleFormat, outputDriverInfo ));
|
||||||
|
DBUG((" %g, %d, %d, 0x%x, , %p )\n",
|
||||||
|
sampleRate, framesPerBuffer, numberOfBuffers,
|
||||||
|
streamFlags, userData ));
|
||||||
|
|
||||||
|
/* Check for parameter errors. */
|
||||||
|
if( (streamFlags & ~(paClipOff | paDitherOff)) != 0 ) return paInvalidFlag;
|
||||||
|
if( streamPtrPtr == NULL ) return paBadStreamPtr;
|
||||||
|
if( inputDriverInfo != NULL ) return paHostError; /* REVIEW */
|
||||||
|
if( outputDriverInfo != NULL ) return paHostError; /* REVIEW */
|
||||||
|
if( (inputDeviceID < 0) && ( outputDeviceID < 0) ) return paInvalidDeviceId;
|
||||||
|
if( (outputDeviceID >= Pa_CountDevices()) || (inputDeviceID >= Pa_CountDevices()) ) return paInvalidDeviceId;
|
||||||
|
if( (numInputChannels <= 0) && ( numOutputChannels <= 0) ) return paInvalidChannelCount;
|
||||||
|
|
||||||
|
#if SUPPORT_AUDIO_CAPTURE
|
||||||
|
if( inputDeviceID >= 0 )
|
||||||
|
{
|
||||||
|
PaError size = Pa_GetSampleSize( inputSampleFormat );
|
||||||
|
if( size < 0 ) return size;
|
||||||
|
bitsPerInputSample = 8 * size;
|
||||||
|
if( (numInputChannels <= 0) ) return paInvalidChannelCount;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if( inputDeviceID >= 0 )
|
||||||
|
{
|
||||||
|
return paInvalidChannelCount;
|
||||||
|
}
|
||||||
|
#endif /* SUPPORT_AUDIO_CAPTURE */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( numInputChannels > 0 ) return paInvalidChannelCount;
|
||||||
|
bitsPerInputSample = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( outputDeviceID >= 0 )
|
||||||
|
{
|
||||||
|
PaError size = Pa_GetSampleSize( outputSampleFormat );
|
||||||
|
if( size < 0 ) return size;
|
||||||
|
bitsPerOutputSample = 8 * size;
|
||||||
|
if( (numOutputChannels <= 0) ) return paInvalidChannelCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( numOutputChannels > 0 ) return paInvalidChannelCount;
|
||||||
|
bitsPerOutputSample = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( callback == NULL ) return paNullCallback;
|
||||||
|
|
||||||
|
/* Allocate and clear stream structure. */
|
||||||
|
past = (internalPortAudioStream *) PaHost_AllocateFastMemory( sizeof(internalPortAudioStream) );
|
||||||
|
if( past == NULL ) return paInsufficientMemory;
|
||||||
|
memset( past, 0, sizeof(internalPortAudioStream) );
|
||||||
|
AddTraceMessage("Pa_OpenStream: past", (long) past );
|
||||||
|
|
||||||
|
past->past_Magic = PA_MAGIC; /* Set ID to catch bugs. */
|
||||||
|
past->past_FramesPerUserBuffer = framesPerBuffer;
|
||||||
|
past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() NMUST CHECK FOR ZERO! */
|
||||||
|
past->past_Callback = callback;
|
||||||
|
past->past_UserData = userData;
|
||||||
|
past->past_OutputSampleFormat = outputSampleFormat;
|
||||||
|
past->past_InputSampleFormat = inputSampleFormat;
|
||||||
|
past->past_OutputDeviceID = outputDeviceID;
|
||||||
|
past->past_InputDeviceID = inputDeviceID;
|
||||||
|
past->past_NumInputChannels = numInputChannels;
|
||||||
|
past->past_NumOutputChannels = numOutputChannels;
|
||||||
|
past->past_Flags = streamFlags;
|
||||||
|
|
||||||
|
/* Check for absurd sample rates. */
|
||||||
|
if( (sampleRate < 1000.0) || (sampleRate > 200000.0) )
|
||||||
|
{
|
||||||
|
result = paInvalidSampleRate;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffers that may be used for format conversion from user to native buffers. */
|
||||||
|
if( numInputChannels > 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
#if PA_VALIDATE_RATE
|
||||||
|
result = PaHost_ValidateSampleRate( inputDeviceID, sampleRate, &past->past_SampleRate );
|
||||||
|
if( result < 0 )
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
past->past_SampleRate = sampleRate;
|
||||||
|
#endif
|
||||||
|
/* Allocate single Input buffer. */
|
||||||
|
past->past_InputBufferSize = framesPerBuffer * numInputChannels * ((bitsPerInputSample+7) / 8);
|
||||||
|
past->past_InputBuffer = PaHost_AllocateFastMemory(past->past_InputBufferSize);
|
||||||
|
if( past->past_InputBuffer == NULL )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
past->past_InputBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate single Output buffer. */
|
||||||
|
if( numOutputChannels > 0 )
|
||||||
|
{
|
||||||
|
#if PA_VALIDATE_RATE
|
||||||
|
result = PaHost_ValidateSampleRate( outputDeviceID, sampleRate, &past->past_SampleRate );
|
||||||
|
if( result < 0 )
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
past->past_SampleRate = sampleRate;
|
||||||
|
#endif
|
||||||
|
past->past_OutputBufferSize = framesPerBuffer * numOutputChannels * ((bitsPerOutputSample+7) / 8);
|
||||||
|
past->past_OutputBuffer = PaHost_AllocateFastMemory(past->past_OutputBufferSize);
|
||||||
|
if( past->past_OutputBuffer == NULL )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
past->past_OutputBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = PaHost_OpenStream( past );
|
||||||
|
if( result < 0 ) goto cleanup;
|
||||||
|
|
||||||
|
*streamPtrPtr = (void *) past;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if( past != NULL ) Pa_CloseStream( past );
|
||||||
|
*streamPtrPtr = NULL;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_OpenDefaultStream( PortAudioStream** stream,
|
||||||
|
int numInputChannels,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat sampleFormat,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData )
|
||||||
|
{
|
||||||
|
return Pa_OpenStream(
|
||||||
|
stream,
|
||||||
|
((numInputChannels > 0) ? Pa_GetDefaultInputDeviceID() : paNoDevice),
|
||||||
|
numInputChannels, sampleFormat, NULL,
|
||||||
|
((numOutputChannels > 0) ? Pa_GetDefaultOutputDeviceID() : paNoDevice),
|
||||||
|
numOutputChannels, sampleFormat, NULL,
|
||||||
|
sampleRate, framesPerBuffer, numberOfBuffers, paNoFlag, callback, userData );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_CloseStream( PortAudioStream* stream)
|
||||||
|
{
|
||||||
|
PaError result;
|
||||||
|
internalPortAudioStream *past;
|
||||||
|
|
||||||
|
DBUG(("Pa_CloseStream()\n"));
|
||||||
|
if( stream == NULL ) return paBadStreamPtr;
|
||||||
|
past = (internalPortAudioStream *) stream;
|
||||||
|
|
||||||
|
Pa_AbortStream( past );
|
||||||
|
result = PaHost_CloseStream( past );
|
||||||
|
|
||||||
|
if( past->past_InputBuffer ) PaHost_FreeFastMemory( past->past_InputBuffer, past->past_InputBufferSize );
|
||||||
|
if( past->past_OutputBuffer ) PaHost_FreeFastMemory( past->past_OutputBuffer, past->past_OutputBufferSize );
|
||||||
|
PaHost_FreeFastMemory( past, sizeof(internalPortAudioStream) );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_StartStream( PortAudioStream *stream )
|
||||||
|
{
|
||||||
|
PaError result = paHostError;
|
||||||
|
internalPortAudioStream *past;
|
||||||
|
|
||||||
|
if( stream == NULL ) return paBadStreamPtr;
|
||||||
|
past = (internalPortAudioStream *) stream;
|
||||||
|
|
||||||
|
past->past_FrameCount = 0.0;
|
||||||
|
|
||||||
|
if( past->past_NumInputChannels > 0 )
|
||||||
|
{
|
||||||
|
result = PaHost_StartInput( past );
|
||||||
|
DBUG(("Pa_StartStream: PaHost_StartInput returned = 0x%X.\n", result));
|
||||||
|
if( result < 0 ) goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( past->past_NumOutputChannels > 0 )
|
||||||
|
{
|
||||||
|
result = PaHost_StartOutput( past );
|
||||||
|
DBUG(("Pa_StartStream: PaHost_StartOutput returned = 0x%X.\n", result));
|
||||||
|
if( result < 0 ) goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = PaHost_StartEngine( past );
|
||||||
|
DBUG(("Pa_StartStream: PaHost_StartEngine returned = 0x%X.\n", result));
|
||||||
|
if( result < 0 ) goto error;
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_StopStream( PortAudioStream *stream )
|
||||||
|
{
|
||||||
|
return Pa_KillStream( stream, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_AbortStream( PortAudioStream *stream )
|
||||||
|
{
|
||||||
|
return Pa_KillStream( stream, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
static PaError Pa_KillStream( PortAudioStream *stream, int abort )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
internalPortAudioStream *past;
|
||||||
|
|
||||||
|
DBUG(("Pa_StopStream().\n"));
|
||||||
|
if( stream == NULL ) return paBadStreamPtr;
|
||||||
|
past = (internalPortAudioStream *) stream;
|
||||||
|
|
||||||
|
if( (past->past_NumInputChannels > 0) || (past->past_NumOutputChannels > 0) )
|
||||||
|
{
|
||||||
|
result = PaHost_StopEngine( past, abort );
|
||||||
|
DBUG(("Pa_StopStream: PaHost_StopEngine returned = 0x%X.\n", result));
|
||||||
|
if( result < 0 ) goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( past->past_NumInputChannels > 0 )
|
||||||
|
{
|
||||||
|
result = PaHost_StopInput( past, abort );
|
||||||
|
DBUG(("Pa_StopStream: PaHost_StopInput returned = 0x%X.\n", result));
|
||||||
|
if( result != paNoError ) goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( past->past_NumOutputChannels > 0 )
|
||||||
|
{
|
||||||
|
result = PaHost_StopOutput( past, abort );
|
||||||
|
DBUG(("Pa_StopStream: PaHost_StopOutput returned = 0x%X.\n", result));
|
||||||
|
if( result != paNoError ) goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
past->past_Usage = 0;
|
||||||
|
past->past_IfLastExitValid = 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_StreamActive( PortAudioStream *stream )
|
||||||
|
{
|
||||||
|
internalPortAudioStream *past;
|
||||||
|
if( stream == NULL ) return paBadStreamPtr;
|
||||||
|
past = (internalPortAudioStream *) stream;
|
||||||
|
return PaHost_StreamActive( past );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API const char *Pa_GetErrorText( PaError errnum )
|
||||||
|
{
|
||||||
|
const char *msg;
|
||||||
|
|
||||||
|
switch(errnum)
|
||||||
|
{
|
||||||
|
case paNoError: msg = "Success"; break;
|
||||||
|
case paHostError: msg = "Host error."; break;
|
||||||
|
case paInvalidChannelCount: msg = "Invalid number of channels."; break;
|
||||||
|
case paInvalidSampleRate: msg = "Invalid sample rate."; break;
|
||||||
|
case paInvalidDeviceId: msg = "Invalid device ID."; break;
|
||||||
|
case paInvalidFlag: msg = "Invalid flag."; break;
|
||||||
|
case paSampleFormatNotSupported: msg = "Sample format not supported"; break;
|
||||||
|
case paBadIODeviceCombination: msg = "Illegal combination of I/O devices."; break;
|
||||||
|
case paInsufficientMemory: msg = "Insufficient memory."; break;
|
||||||
|
case paBufferTooBig: msg = "Buffer too big."; break;
|
||||||
|
case paBufferTooSmall: msg = "Buffer too small."; break;
|
||||||
|
case paNullCallback: msg = "No callback routine specified."; break;
|
||||||
|
case paBadStreamPtr: msg = "Invalid stream pointer."; break;
|
||||||
|
case paTimedOut : msg = "Wait Timed Out."; break;
|
||||||
|
case paInternalError: msg = "Internal PortAudio Error."; break;
|
||||||
|
default: msg = "Illegal error number."; break;
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get CPU Load as a fraction of total CPU time.
|
||||||
|
A value of 0.5 would imply that PortAudio and the sound generating
|
||||||
|
callback was consuming roughly 50% of the available CPU time.
|
||||||
|
The amount may vary depending on CPU load.
|
||||||
|
This function may be called from the callback function.
|
||||||
|
*/
|
||||||
|
DLL_API double Pa_GetCPULoad( PortAudioStream* stream)
|
||||||
|
{
|
||||||
|
internalPortAudioStream *past;
|
||||||
|
if( stream == NULL ) return (double) paBadStreamPtr;
|
||||||
|
past = (internalPortAudioStream *) stream;
|
||||||
|
return past->past_Usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
** Calculate 2 LSB dither signal with a triangular distribution.
|
||||||
|
** Ranged properly for adding to a 32 bit integer prior to >>15.
|
||||||
|
*/
|
||||||
|
#define DITHER_BITS (15)
|
||||||
|
#define DITHER_SCALE (1.0f / ((1<<DITHER_BITS)-1))
|
||||||
|
static long Pa_TriangularDither( void )
|
||||||
|
{
|
||||||
|
static unsigned long previous = 0;
|
||||||
|
static unsigned long randSeed1 = 22222;
|
||||||
|
static unsigned long randSeed2 = 5555555;
|
||||||
|
long current, highPass;
|
||||||
|
/* Generate two random numbers. */
|
||||||
|
randSeed1 = (randSeed1 * 196314165) + 907633515;
|
||||||
|
randSeed2 = (randSeed2 * 196314165) + 907633515;
|
||||||
|
/* Generate triangular distribution about 0. */
|
||||||
|
current = (((long)randSeed1)>>(32-DITHER_BITS)) + (((long)randSeed2)>>(32-DITHER_BITS));
|
||||||
|
/* High pass filter to reduce audibility. */
|
||||||
|
highPass = current - previous;
|
||||||
|
previous = current;
|
||||||
|
return highPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
** Called by host code.
|
||||||
|
** Convert input from Int16, call user code, then convert output
|
||||||
|
** to Int16 format for native use.
|
||||||
|
** Assumes host native format is paInt16.
|
||||||
|
** Returns result from user callback.
|
||||||
|
*/
|
||||||
|
long Pa_CallConvertInt16( internalPortAudioStream *past,
|
||||||
|
short *nativeInputBuffer,
|
||||||
|
short *nativeOutputBuffer )
|
||||||
|
{
|
||||||
|
long temp;
|
||||||
|
long bytesEmpty = 0;
|
||||||
|
long bytesFilled = 0;
|
||||||
|
int userResult;
|
||||||
|
unsigned int i;
|
||||||
|
void *inputBuffer = NULL;
|
||||||
|
void *outputBuffer = NULL;
|
||||||
|
|
||||||
|
#if SUPPORT_AUDIO_CAPTURE
|
||||||
|
/* Get native data from DirectSound. */
|
||||||
|
if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) )
|
||||||
|
{
|
||||||
|
/* Convert from native format to PA format. */
|
||||||
|
unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels;
|
||||||
|
switch(past->past_InputSampleFormat)
|
||||||
|
{
|
||||||
|
|
||||||
|
case paFloat32:
|
||||||
|
{
|
||||||
|
float *inBufPtr = (float *) past->past_InputBuffer;
|
||||||
|
inputBuffer = past->past_InputBuffer;
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
inBufPtr[i] = nativeInputBuffer[i] * (1.0f / 32767.0f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paInt32:
|
||||||
|
{
|
||||||
|
/* Convert 16 bit data to 32 bit integers */
|
||||||
|
int *inBufPtr = (int *) past->past_InputBuffer;
|
||||||
|
inputBuffer = past->past_InputBuffer;
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
inBufPtr[i] = nativeInputBuffer[i] << 16;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paInt16:
|
||||||
|
{
|
||||||
|
/* Already in correct format so don't copy. */
|
||||||
|
inputBuffer = nativeInputBuffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paInt8:
|
||||||
|
{
|
||||||
|
/* Convert 16 bit data to 8 bit chars */
|
||||||
|
char *inBufPtr = (char *) past->past_InputBuffer;
|
||||||
|
inputBuffer = past->past_InputBuffer;
|
||||||
|
if( past->past_Flags & paDitherOff )
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
inBufPtr[i] = (char)(nativeInputBuffer[i] >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
temp = nativeInputBuffer[i];
|
||||||
|
temp += Pa_TriangularDither() >> 7;
|
||||||
|
temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||||
|
inBufPtr[i] = (char)(temp >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paUInt8:
|
||||||
|
{
|
||||||
|
/* Convert 16 bit data to 8 bit unsigned chars */
|
||||||
|
unsigned char *inBufPtr = (unsigned char *) past->past_InputBuffer;
|
||||||
|
inputBuffer = past->past_InputBuffer;
|
||||||
|
if( past->past_Flags & paDitherOff )
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
inBufPtr[i] = ((unsigned char)(nativeInputBuffer[i] >> 8)) + 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If you dither then you have to clip because dithering could push the signal out of range! */
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
temp = nativeInputBuffer[i];
|
||||||
|
temp += Pa_TriangularDither() >> 7;
|
||||||
|
temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||||
|
inBufPtr[i] = (unsigned char)(temp + 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SUPPORT_AUDIO_CAPTURE */
|
||||||
|
|
||||||
|
/* Are we doing output time? */
|
||||||
|
if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) )
|
||||||
|
{
|
||||||
|
/* May already be in native format so just write directly to native buffer. */
|
||||||
|
outputBuffer = (past->past_OutputSampleFormat == paInt16) ?
|
||||||
|
nativeOutputBuffer : past->past_OutputBuffer;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer );
|
||||||
|
AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer );
|
||||||
|
*/
|
||||||
|
/* Call user callback routine. */
|
||||||
|
userResult = past->past_Callback(
|
||||||
|
inputBuffer,
|
||||||
|
outputBuffer,
|
||||||
|
past->past_FramesPerUserBuffer,
|
||||||
|
past->past_FrameCount,
|
||||||
|
past->past_UserData );
|
||||||
|
|
||||||
|
past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer;
|
||||||
|
|
||||||
|
/* Convert to native format if necessary. */
|
||||||
|
if( outputBuffer != NULL )
|
||||||
|
{
|
||||||
|
unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels;
|
||||||
|
switch(past->past_OutputSampleFormat)
|
||||||
|
{
|
||||||
|
case paFloat32:
|
||||||
|
{
|
||||||
|
float *outBufPtr = (float *) past->past_OutputBuffer;
|
||||||
|
if( past->past_Flags & paDitherOff )
|
||||||
|
{
|
||||||
|
if( past->past_Flags & paClipOff ) /* NOTHING */
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
*nativeOutputBuffer++ = (short) (outBufPtr[i] * (32767.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* CLIP */
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
temp = (long)(outBufPtr[i] * 32767.0f);
|
||||||
|
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If you dither then you have to clip because dithering could push the signal out of range! */
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
float dither = Pa_TriangularDither()*DITHER_SCALE;
|
||||||
|
float dithered = (outBufPtr[i] * (32767.0f)) + dither;
|
||||||
|
temp = (long) (dithered);
|
||||||
|
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paInt32:
|
||||||
|
{
|
||||||
|
int *outBufPtr = (int *) past->past_OutputBuffer;
|
||||||
|
if( past->past_Flags & paDitherOff )
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
*nativeOutputBuffer++ = (short) (outBufPtr[i] >> 16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
/* Shift one bit down before dithering so that we have room for overflow from add. */
|
||||||
|
temp = (outBufPtr[i] >> 1) + Pa_TriangularDither();
|
||||||
|
temp = temp >> 15;
|
||||||
|
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paInt8:
|
||||||
|
{
|
||||||
|
char *outBufPtr = (char *) past->past_OutputBuffer;
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
*nativeOutputBuffer++ = ((short)outBufPtr[i]) << 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case paUInt8:
|
||||||
|
{
|
||||||
|
unsigned char *outBufPtr = (unsigned char *) past->past_OutputBuffer;
|
||||||
|
for( i=0; i<samplesPerBuffer; i++ )
|
||||||
|
{
|
||||||
|
*nativeOutputBuffer++ = ((short)(outBufPtr[i] - 0x80)) << 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return userResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
** Called by host code.
|
||||||
|
** Convert input from Float32, call user code, then convert output
|
||||||
|
** to Float32 format for native use.
|
||||||
|
** Assumes host native format is Float32.
|
||||||
|
** Returns result from user callback.
|
||||||
|
** FIXME - Unimplemented for formats other than paFloat32!!!!
|
||||||
|
*/
|
||||||
|
long Pa_CallConvertFloat32( internalPortAudioStream *past,
|
||||||
|
float *nativeInputBuffer,
|
||||||
|
float *nativeOutputBuffer )
|
||||||
|
{
|
||||||
|
long bytesEmpty = 0;
|
||||||
|
long bytesFilled = 0;
|
||||||
|
int userResult;
|
||||||
|
void *inputBuffer = NULL;
|
||||||
|
void *outputBuffer = NULL;
|
||||||
|
|
||||||
|
/* Get native data from DirectSound. */
|
||||||
|
if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) )
|
||||||
|
{
|
||||||
|
inputBuffer = nativeInputBuffer; // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are we doing output time? */
|
||||||
|
if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) )
|
||||||
|
{
|
||||||
|
/* May already be in native format so just write directly to native buffer. */
|
||||||
|
outputBuffer = (past->past_OutputSampleFormat == paFloat32) ?
|
||||||
|
nativeOutputBuffer : past->past_OutputBuffer;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer );
|
||||||
|
AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer );
|
||||||
|
*/
|
||||||
|
/* Call user callback routine. */
|
||||||
|
userResult = past->past_Callback(
|
||||||
|
inputBuffer,
|
||||||
|
outputBuffer,
|
||||||
|
past->past_FramesPerUserBuffer,
|
||||||
|
past->past_FrameCount,
|
||||||
|
past->past_UserData );
|
||||||
|
|
||||||
|
past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer;
|
||||||
|
|
||||||
|
/* Convert to native format if necessary. */ // FIXME
|
||||||
|
return userResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_Initialize( void )
|
||||||
|
{
|
||||||
|
if( gInitCount++ > 0 ) return paNoError;
|
||||||
|
ResetTraceMessages();
|
||||||
|
return PaHost_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
DLL_API PaError Pa_Terminate( void )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
|
||||||
|
if( gInitCount == 0 ) return paNoError;
|
||||||
|
else if( --gInitCount == 0 )
|
||||||
|
{
|
||||||
|
result = PaHost_Term();
|
||||||
|
DumpTraceMessages();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
DLL_API PaError Pa_GetSampleSize( PaSampleFormat format )
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
switch(format )
|
||||||
|
{
|
||||||
|
|
||||||
|
case paUInt8:
|
||||||
|
case paInt8:
|
||||||
|
size = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt16:
|
||||||
|
size = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paPackedInt24:
|
||||||
|
size = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paFloat32:
|
||||||
|
case paInt32:
|
||||||
|
case paInt24:
|
||||||
|
size = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
size = paSampleFormatNotSupported;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (PaError) size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
439
portaudio-v19/pa_dll_switch/portaudio.h
Normal file
439
portaudio-v19/pa_dll_switch/portaudio.h
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
#ifndef PORT_AUDIO_H
|
||||||
|
#define PORT_AUDIO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* PortAudio API Header File
|
||||||
|
* Latest version available at: 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// added by zplane.developement in order to generate a DLL
|
||||||
|
|
||||||
|
#if defined(PA_MME_EXPORTS) || defined(PA_DX_EXPORTS)
|
||||||
|
#define DLL_API __declspec( dllexport )
|
||||||
|
#elif defined(_LIB) || defined(_STATIC_LINK) || defined(_STATIC_APP)
|
||||||
|
#define DLL_API
|
||||||
|
#else
|
||||||
|
#define DLL_API __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef int PaError;
|
||||||
|
typedef enum {
|
||||||
|
paNoError = 0,
|
||||||
|
|
||||||
|
paHostError = -10000,
|
||||||
|
paInvalidChannelCount,
|
||||||
|
paInvalidSampleRate,
|
||||||
|
paInvalidDeviceId,
|
||||||
|
paInvalidFlag,
|
||||||
|
paSampleFormatNotSupported,
|
||||||
|
paBadIODeviceCombination,
|
||||||
|
paInsufficientMemory,
|
||||||
|
paBufferTooBig,
|
||||||
|
paBufferTooSmall,
|
||||||
|
paNullCallback,
|
||||||
|
paBadStreamPtr,
|
||||||
|
paTimedOut,
|
||||||
|
paInternalError
|
||||||
|
} PaErrorNum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_Initialize() is the library initialisation function - call this before
|
||||||
|
using the library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_Initialize( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_Terminate() is the library termination function - call this after
|
||||||
|
using the library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_Terminate( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return host specific error.
|
||||||
|
This can be called after receiving a paHostError.
|
||||||
|
*/
|
||||||
|
DLL_API long Pa_GetHostError( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translate the error number into a human readable message.
|
||||||
|
*/
|
||||||
|
DLL_API const char *Pa_GetErrorText( PaError errnum );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sample formats
|
||||||
|
|
||||||
|
These are formats used to pass sound data between the callback and the
|
||||||
|
stream. Each device has a "native" format which may be used when optimum
|
||||||
|
efficiency or control over conversion is required.
|
||||||
|
|
||||||
|
Formats marked "always available" are supported (emulated) by all devices.
|
||||||
|
|
||||||
|
The floating point representation uses +1.0 and -1.0 as the respective
|
||||||
|
maximum and minimum.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef unsigned long PaSampleFormat;
|
||||||
|
#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/
|
||||||
|
#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/
|
||||||
|
#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/
|
||||||
|
#define paInt24 ((PaSampleFormat) (1<<3))
|
||||||
|
#define paPackedInt24 ((PaSampleFormat) (1<<4))
|
||||||
|
#define paInt8 ((PaSampleFormat) (1<<5))
|
||||||
|
#define paUInt8 ((PaSampleFormat) (1<<6)) /* unsigned 8 bit, 128 is "ground" */
|
||||||
|
#define paCustomFormat ((PaSampleFormat) (1<<16))
|
||||||
|
|
||||||
|
/*
|
||||||
|
Device enumeration mechanism.
|
||||||
|
|
||||||
|
Device ids range from 0 to Pa_CountDevices()-1.
|
||||||
|
|
||||||
|
Devices may support input, output or both. Device 0 is always the "default"
|
||||||
|
device and should support at least stereo in and out if that is available
|
||||||
|
on the taget platform _even_ if this involves kludging an input/output
|
||||||
|
device on platforms that usually separate input from output. Other platform
|
||||||
|
specific devices are specified by positive device ids.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int PaDeviceID;
|
||||||
|
#define paNoDevice -1
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int structVersion;
|
||||||
|
const char *name;
|
||||||
|
int maxInputChannels;
|
||||||
|
int maxOutputChannels;
|
||||||
|
/* Number of discrete rates, or -1 if range supported. */
|
||||||
|
int numSampleRates;
|
||||||
|
/* Array of supported sample rates, or {min,max} if range supported. */
|
||||||
|
const double *sampleRates;
|
||||||
|
PaSampleFormat nativeSampleFormats;
|
||||||
|
}
|
||||||
|
PaDeviceInfo;
|
||||||
|
|
||||||
|
|
||||||
|
DLL_API int Pa_CountDevices();
|
||||||
|
/*
|
||||||
|
Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID()
|
||||||
|
|
||||||
|
Return the default device ID or paNoDevice if there is no devices.
|
||||||
|
The result can be passed to Pa_OpenStream().
|
||||||
|
|
||||||
|
On the PC, the user can specify a default device by
|
||||||
|
setting an environment variable. For example, to use device #1.
|
||||||
|
|
||||||
|
set PA_RECOMMENDED_OUTPUT_DEVICE=1
|
||||||
|
|
||||||
|
The user should first determine the available device ID by using
|
||||||
|
the supplied application "pa_devs".
|
||||||
|
*/
|
||||||
|
DLL_API PaDeviceID Pa_GetDefaultInputDeviceID( void );
|
||||||
|
DLL_API PaDeviceID Pa_GetDefaultOutputDeviceID( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
PaTimestamp is used to represent a continuous sample clock with arbitrary
|
||||||
|
start time useful for syncronisation. The type is used in the outTime
|
||||||
|
argument to the callback function and the result of Pa_StreamTime()
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef double PaTimestamp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure
|
||||||
|
referring to the device specified by id.
|
||||||
|
If id is out of range the function returns NULL.
|
||||||
|
|
||||||
|
The returned structure is owned by the PortAudio implementation and must
|
||||||
|
not be manipulated or freed. The pointer is guaranteed to be valid until
|
||||||
|
between calls to Pa_Initialize() and Pa_Terminate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id );
|
||||||
|
|
||||||
|
/*
|
||||||
|
PortAudioCallback is implemented by clients of the portable audio api.
|
||||||
|
|
||||||
|
inputBuffer and outputBuffer are arrays of interleaved samples,
|
||||||
|
the format, packing and number of channels used by the buffers are
|
||||||
|
determined by parameters to Pa_OpenStream() (see below).
|
||||||
|
|
||||||
|
framesPerBuffer is the number of sample frames to be processed by the callback.
|
||||||
|
|
||||||
|
outTime is the time in samples when the buffer(s) processed by
|
||||||
|
this callback will begin being played at the audio output.
|
||||||
|
See also Pa_StreamTime()
|
||||||
|
|
||||||
|
userData is the value of a user supplied pointer passed to Pa_OpenStream()
|
||||||
|
intended for storing synthesis data etc.
|
||||||
|
|
||||||
|
return value:
|
||||||
|
The callback can return a nonzero value to stop the stream. This may be
|
||||||
|
useful in applications such as soundfile players where a specific duration
|
||||||
|
of output is required. However, it is not necessary to utilise this mechanism
|
||||||
|
as StopStream() will also terminate the stream. A callback returning a
|
||||||
|
nonzero value must fill the entire outputBuffer.
|
||||||
|
|
||||||
|
NOTE: None of the other stream functions may be called from within the
|
||||||
|
callback function except for Pa_GetCPULoad().
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int (PortAudioCallback)(
|
||||||
|
void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaTimestamp outTime, void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Stream flags
|
||||||
|
|
||||||
|
These flags may be supplied (ored together) in the streamFlags argument to
|
||||||
|
the Pa_OpenStream() function.
|
||||||
|
|
||||||
|
[ suggestions? ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define paNoFlag (0)
|
||||||
|
#define paClipOff (1<<0) /* disable defult clipping of out of range samples */
|
||||||
|
#define paDitherOff (1<<1) /* disable default dithering */
|
||||||
|
#define paPlatformSpecificFlags (0x00010000)
|
||||||
|
typedef unsigned long PaStreamFlags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
A single PortAudioStream provides multiple channels of real-time
|
||||||
|
input and output audio streaming to a client application.
|
||||||
|
Pointers to PortAudioStream objects are passed between PortAudio functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void PortAudioStream;
|
||||||
|
#define PaStream PortAudioStream
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_OpenStream() opens a stream for either input, output or both.
|
||||||
|
|
||||||
|
stream is the address of a PortAudioStream pointer which will receive
|
||||||
|
a pointer to the newly opened stream.
|
||||||
|
|
||||||
|
inputDevice is the id of the device used for input (see PaDeviceID above.)
|
||||||
|
inputDevice may be paNoDevice to indicate that an input device is not required.
|
||||||
|
|
||||||
|
numInputChannels is the number of channels of sound to be delivered to the
|
||||||
|
callback. It can range from 1 to the value of maxInputChannels in the
|
||||||
|
device input record for the device specified in the inputDevice parameter.
|
||||||
|
If inputDevice is paNoDevice numInputChannels is ignored.
|
||||||
|
|
||||||
|
inputSampleFormat is the format of inputBuffer provided to the callback
|
||||||
|
function. inputSampleFormat may be any of the formats described by the
|
||||||
|
PaSampleFormat enumeration (see above). PortAudio guarantees support for
|
||||||
|
the sound devices native formats (nativeSampleFormats in the device info
|
||||||
|
record) and additionally 16 and 32 bit integer and 32 bit floating point
|
||||||
|
formats. Support for other formats is implementation defined.
|
||||||
|
|
||||||
|
inputDriverInfo is a pointer to an optional driver specific data structure
|
||||||
|
containing additional information for device setup or stream processing.
|
||||||
|
inputDriverInfo is never required for correct operation. If not used
|
||||||
|
inputDriverInfo should be NULL.
|
||||||
|
|
||||||
|
outputDevice is the id of the device used for output (see PaDeviceID above.)
|
||||||
|
outputDevice may be paNoDevice to indicate that an output device is not required.
|
||||||
|
|
||||||
|
numOutputChannels is the number of channels of sound to be supplied by the
|
||||||
|
callback. See the definition of numInputChannels above for more details.
|
||||||
|
|
||||||
|
outputSampleFormat is the sample format of the outputBuffer filled by the
|
||||||
|
callback function. See the definition of inputSampleFormat above for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
outputDriverInfo is a pointer to an optional driver specific data structure
|
||||||
|
containing additional information for device setup or stream processing.
|
||||||
|
outputDriverInfo is never required for correct operation. If not used
|
||||||
|
outputDriverInfo should be NULL.
|
||||||
|
|
||||||
|
sampleRate is the desired sampleRate for input and output
|
||||||
|
|
||||||
|
framesPerBuffer is the length in sample frames of all internal sample buffers
|
||||||
|
used for communication with platform specific audio routines. Wherever
|
||||||
|
possible this corresponds to the framesPerBuffer parameter passed to the
|
||||||
|
callback function.
|
||||||
|
|
||||||
|
numberOfBuffers is the number of buffers used for multibuffered
|
||||||
|
communication with the platform specific audio routines. This parameter is
|
||||||
|
provided only as a guide - and does not imply that an implementation must
|
||||||
|
use multibuffered i/o when reliable double buffering is available (such as
|
||||||
|
SndPlayDoubleBuffer() on the Macintosh.)
|
||||||
|
|
||||||
|
streamFlags may contain a combination of flags ORed together.
|
||||||
|
These flags modify the behavior of the
|
||||||
|
streaming process. Some flags may only be relevant to certain buffer formats.
|
||||||
|
|
||||||
|
callback is a pointer to a client supplied function that is responsible
|
||||||
|
for processing and filling input and output buffers (see above for details.)
|
||||||
|
|
||||||
|
userData is a client supplied pointer which is passed to the callback
|
||||||
|
function. It could for example, contain a pointer to instance data necessary
|
||||||
|
for processing the audio buffers.
|
||||||
|
|
||||||
|
return value:
|
||||||
|
Apon success Pa_OpenStream() returns PaNoError and places a pointer to a
|
||||||
|
valid PortAudioStream in the stream argument. The stream is inactive (stopped).
|
||||||
|
If a call to Pa_OpenStream() fails a nonzero error code is returned (see
|
||||||
|
PAError above) and the value of stream is invalid.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_OpenStream( PortAudioStream** stream,
|
||||||
|
PaDeviceID inputDevice,
|
||||||
|
int numInputChannels,
|
||||||
|
PaSampleFormat inputSampleFormat,
|
||||||
|
void *inputDriverInfo,
|
||||||
|
PaDeviceID outputDevice,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat outputSampleFormat,
|
||||||
|
void *outputDriverInfo,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that
|
||||||
|
opens the default input and/or ouput devices. Most parameters have
|
||||||
|
identical meaning to their Pa_OpenStream() counterparts, with the following
|
||||||
|
exceptions:
|
||||||
|
|
||||||
|
If either numInputChannels or numOutputChannels is 0 the respective device
|
||||||
|
is not opened (same as passing paNoDevice in the device arguments to Pa_OpenStream() )
|
||||||
|
|
||||||
|
sampleFormat applies to both the input and output buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_OpenDefaultStream( PortAudioStream** stream,
|
||||||
|
int numInputChannels,
|
||||||
|
int numOutputChannels,
|
||||||
|
PaSampleFormat sampleFormat,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
unsigned long numberOfBuffers,
|
||||||
|
PortAudioCallback *callback,
|
||||||
|
void *userData );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_CloseStream() closes an audio stream, flushing any pending buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_CloseStream( PortAudioStream* );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_StartStream() and Pa_StopStream() begin and terminate audio processing.
|
||||||
|
When Pa_StopStream() returns, all pending audio buffers have been played.
|
||||||
|
Pa_AbortStream() stops playing immediately without waiting for pending
|
||||||
|
buffers to complete.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_StartStream( PortAudioStream *stream );
|
||||||
|
|
||||||
|
DLL_API PaError Pa_StopStream( PortAudioStream *stream );
|
||||||
|
|
||||||
|
DLL_API PaError Pa_AbortStream( PortAudioStream *stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_StreamActive() returns one when the stream is playing audio,
|
||||||
|
zero when not playing, or a negative error number if the
|
||||||
|
stream is invalid.
|
||||||
|
The stream is active between calls to Pa_StartStream() and Pa_StopStream(),
|
||||||
|
but may also become inactive if the callback returns a non-zero value.
|
||||||
|
In the latter case, the stream is considered inactive after the last
|
||||||
|
buffer has finished playing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaError Pa_StreamActive( PortAudioStream *stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pa_StreamTime() returns the current output time for the stream in samples.
|
||||||
|
This time may be used as a time reference (for example syncronising audio to
|
||||||
|
MIDI).
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API PaTimestamp Pa_StreamTime( PortAudioStream *stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
The "CPU Load" is a fraction of total CPU time consumed by the
|
||||||
|
stream's audio processing.
|
||||||
|
A value of 0.5 would imply that PortAudio and the sound generating
|
||||||
|
callback was consuming roughly 50% of the available CPU time.
|
||||||
|
This function may be called from the callback function or the application.
|
||||||
|
*/
|
||||||
|
DLL_API double Pa_GetCPULoad( PortAudioStream* stream );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Use Pa_GetMinNumBuffers() to determine minimum number of buffers required for
|
||||||
|
the current host based on minimum latency.
|
||||||
|
On the PC, for the DirectSound implementation, latency can be optionally set
|
||||||
|
by user by setting an environment variable.
|
||||||
|
For example, to set latency to 200 msec, put:
|
||||||
|
|
||||||
|
set PA_MIN_LATENCY_MSEC=200
|
||||||
|
|
||||||
|
in the AUTOEXEC.BAT file and reboot.
|
||||||
|
If the environment variable is not set, then the latency will be determined
|
||||||
|
based on the OS. Windows NT has higher latency than Win95.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DLL_API int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sleep for at least 'msec' milliseconds.
|
||||||
|
You may sleep longer than the requested time so don't rely
|
||||||
|
on this for accurate musical timing.
|
||||||
|
*/
|
||||||
|
DLL_API void Pa_Sleep( long msec );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return size in bytes of a single sample in a given PaSampleFormat
|
||||||
|
or paSampleFormatNotSupported.
|
||||||
|
*/
|
||||||
|
DLL_API PaError Pa_GetSampleSize( PaSampleFormat format );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* PORT_AUDIO_H */
|
||||||
1714
portaudio-v19/pa_jack/pa_jack.c
Normal file
1714
portaudio-v19/pa_jack/pa_jack.c
Normal file
File diff suppressed because it is too large
Load Diff
3590
portaudio-v19/pa_linux_alsa/pa_linux_alsa.c
Normal file
3590
portaudio-v19/pa_linux_alsa/pa_linux_alsa.c
Normal file
File diff suppressed because it is too large
Load Diff
64
portaudio-v19/pa_linux_alsa/pa_linux_alsa.h
Normal file
64
portaudio-v19/pa_linux_alsa/pa_linux_alsa.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef PA_LINUX_ALSA_H
|
||||||
|
#define PA_LINUX_ALSA_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* ALSA-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
|
||||||
|
* ALSA-specific PortAudio API extension header file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct PaAlsaStreamInfo
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
PaHostApiTypeId hostApiType;
|
||||||
|
unsigned long version;
|
||||||
|
|
||||||
|
const char *deviceString;
|
||||||
|
}
|
||||||
|
PaAlsaStreamInfo;
|
||||||
|
|
||||||
|
void PaAlsa_InitializeStreamInfo( PaAlsaStreamInfo *info );
|
||||||
|
|
||||||
|
void PaAlsa_EnableRealtimeScheduling( PaStream *s, int enable );
|
||||||
|
|
||||||
|
void PaAlsa_EnableWatchdog( PaStream *s, int enable );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
79
portaudio-v19/pa_mac/pa_mac_hostapis.c
Normal file
79
portaudio-v19/pa_mac/pa_mac_hostapis.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
124
portaudio-v19/pa_mac_core/notes.txt
Normal file
124
portaudio-v19/pa_mac_core/notes.txt
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
Notes on status of CoreAudio Implementation of PortAudio
|
||||||
|
|
||||||
|
Document Last Updated December 9, 2005
|
||||||
|
|
||||||
|
There are currently two implementations of PortAudio for Mac Core Audio.
|
||||||
|
|
||||||
|
The original is in pa_mac_core_old.c, and the newer one is in pa_mac_core_auhal.c.
|
||||||
|
Only pa_mac_core_auhal.c is currently developed and supported as it uses apple's
|
||||||
|
current core audio technology. To select one of the implementations, copy the
|
||||||
|
appropriate file to pa_mac_core.c, (eg. "cp pa_mac_core_auhal.c pa_mac_core.c")
|
||||||
|
then run configure and make as usual.
|
||||||
|
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
Notes on Original/Default implementation:
|
||||||
|
|
||||||
|
by Phil Burk and Darren Gibbs
|
||||||
|
|
||||||
|
Last updated March 20, 2002
|
||||||
|
|
||||||
|
WHAT WORKS
|
||||||
|
|
||||||
|
Output with very low latency, <10 msec.
|
||||||
|
Half duplex input or output.
|
||||||
|
Full duplex on the same CoreAudio device.
|
||||||
|
The paFLoat32, paInt16, paInt8, paUInt8 sample formats.
|
||||||
|
Pa_GetCPULoad()
|
||||||
|
Pa_StreamTime()
|
||||||
|
|
||||||
|
KNOWN BUGS OR LIMITATIONS
|
||||||
|
|
||||||
|
We do not yet support simultaneous input and output on different
|
||||||
|
devices. Note that some CoreAudio devices like the Roland UH30 look
|
||||||
|
like one device but are actually two different CoreAudio devices. The
|
||||||
|
Built-In audio is typically one CoreAudio device.
|
||||||
|
|
||||||
|
Mono doesn't work.
|
||||||
|
|
||||||
|
DEVICE MAPPING
|
||||||
|
|
||||||
|
CoreAudio devices can support both input and output. But the sample
|
||||||
|
rates supported may be different. So we have map one or two PortAudio
|
||||||
|
device to each CoreAudio device depending on whether it supports
|
||||||
|
input, output or both.
|
||||||
|
|
||||||
|
When we query devices, we first get a list of CoreAudio devices. Then
|
||||||
|
we scan the list and add a PortAudio device for each CoreAudio device
|
||||||
|
that supports input. Then we make a scan for output devices.
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Notes on Newer AUHAL implementation:
|
||||||
|
|
||||||
|
by Bjorn Roche
|
||||||
|
|
||||||
|
Last Updated December 9, 2005
|
||||||
|
|
||||||
|
Principle of Operation:
|
||||||
|
|
||||||
|
This implementation uses AUHAL for audio I/O. To some extent, it also
|
||||||
|
operates at the "HAL" Layer, though this behavior can be limited by
|
||||||
|
platform specific flags (see pa_mac_core.h for details). The default
|
||||||
|
settings should be reasonable: they don't change the SR of the device and
|
||||||
|
don't cause interruptions if other devices are using the device.
|
||||||
|
|
||||||
|
Major Software Elements Used: Apple's HAL AUs provide output SR
|
||||||
|
conversion transparently, however, only on output, so this
|
||||||
|
implementation uses AudioConverters to convert the sample rate on input.
|
||||||
|
A PortAudio ring buffer is used to buffer input when sample rate
|
||||||
|
conversion is required or when separate audio units are used for duplex
|
||||||
|
IO. Finally, a PortAudio buffer processor is used to convert formats and
|
||||||
|
provide additional buffers if needed. Internally, interleaved floating
|
||||||
|
point data streams are used exclusively - the audio unit converts from
|
||||||
|
the audio hardware's native format to interleaved float PCM and
|
||||||
|
PortAudio's Buffer processor is used for conversion to user formats.
|
||||||
|
|
||||||
|
Simplex Input: Simplex input uses a single callback. If sample rate
|
||||||
|
conversion is required, a ring buffer and AudioConverter are used as
|
||||||
|
well.
|
||||||
|
|
||||||
|
Simplex output: Simplex output uses a single callback. No ring buffer or
|
||||||
|
audio converter is used because AUHAL does its own output SR conversion.
|
||||||
|
|
||||||
|
Duplex, one device (no SR conversion): When one device is used, a single
|
||||||
|
callback is used. This achieves very low latency.
|
||||||
|
|
||||||
|
Duplex, separate devices or SR conversion: When SR conversion is
|
||||||
|
required, data must be buffered before it is converted and data is not
|
||||||
|
always available at the same times on input and output, so SR conversion
|
||||||
|
requires the same treatment as separate devices. The input callback
|
||||||
|
reads data and puts it in the ring buffer. The output callback reads the
|
||||||
|
data off the ring buffer, into an audio converter and finally to the
|
||||||
|
buffer processor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Known issues:
|
||||||
|
|
||||||
|
- Latency: Latency settings are ignored except when doing I/O between different
|
||||||
|
devices. Still, latency should be very low.
|
||||||
|
|
||||||
|
- Timing info. It reports on stream time, but I'm probably doing something
|
||||||
|
wrong since patest_sine_time often reports negative latency numbers.
|
||||||
|
|
||||||
|
- xrun detection: The only xrun detection performed is when reading
|
||||||
|
and writing the ring buffer. There is probably more that can be done.
|
||||||
|
|
||||||
|
- abort/stop issues: stopping a stream is always a complete operation,
|
||||||
|
but latency should be low enough to make the lack of a separate abort
|
||||||
|
unnecessary. Apple clarifies its AudioOutputUnitStop() call here:
|
||||||
|
http://lists.apple.com/archives/coreaudio-api/2005/Dec/msg00055.html
|
||||||
|
|
||||||
|
- blocking interface: Not implemented.
|
||||||
|
|
||||||
|
- multichannel: I don't have a multichannel IO box, so I didn't test it.
|
||||||
|
It should work though ;) I haven't done anything with "channel maps"
|
||||||
|
yet, so it's possible that more needs to be done.
|
||||||
|
|
||||||
|
- sample rate conversion quality: the input audio converter is set to
|
||||||
|
the highest quality. I don't do anything about the output converter, and
|
||||||
|
I am not sure how AUHAL manages quality.
|
||||||
|
|
||||||
|
- x86: I haven't tested it on an x86 Mac, but I tried to be aware of it, so
|
||||||
|
it should work without too much trouble.
|
||||||
64
portaudio-v19/pa_mac_core/pa_mac_core.h
Normal file
64
portaudio-v19/pa_mac_core/pa_mac_core.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Mac spcific flags for PA.
|
||||||
|
* portaudio.h should be included before this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A pointer to a paMacCoreStreamInfo may be passed as
|
||||||
|
* the hostApiSpecificStreamInfo in the PaStreamParameters struct
|
||||||
|
* when opening a stream. Use NULL, for the defaults. Note that for
|
||||||
|
* duplex streams, both infos should be the same or behaviour
|
||||||
|
* is undefined.
|
||||||
|
*/
|
||||||
|
typedef struct paMacCoreStreamInfo
|
||||||
|
{
|
||||||
|
unsigned long size; /**< size of whole structure including this header */
|
||||||
|
PaHostApiTypeId hostApiType;/**< host API for which this data is intended */
|
||||||
|
unsigned long version; /**< structure version */
|
||||||
|
unsigned long flags; /* flags to modify behaviour */
|
||||||
|
} paMacCoreStreamInfo;
|
||||||
|
|
||||||
|
/* Use this function to initialize a paMacCoreStreamInfo struct
|
||||||
|
using the requested flags. */
|
||||||
|
void paSetupMacCoreStreamInfo( paMacCoreStreamInfo *data, unsigned long flags )
|
||||||
|
{
|
||||||
|
bzero( data, sizeof( paMacCoreStreamInfo ) );
|
||||||
|
data->size = sizeof( paMacCoreStreamInfo );
|
||||||
|
data->hostApiType = paCoreAudio;
|
||||||
|
data->version = 0x01;
|
||||||
|
data->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here is the struct that shoul
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following flags alter the behaviour of PA on the mac platform.
|
||||||
|
* they can be ORed together. These should work both for opening and
|
||||||
|
* checking a device.
|
||||||
|
*/
|
||||||
|
/* Allows PortAudio to change things like the device's frame size,
|
||||||
|
* which allows for much lower latency, but might disrupt the device
|
||||||
|
* if other programs are using it. */
|
||||||
|
const unsigned long paMacCore_ChangeDeviceParameters = 0x01;
|
||||||
|
|
||||||
|
/* In combination with the above flag,
|
||||||
|
* causes the stream opening to fail, unless the exact sample rates
|
||||||
|
* are supported by the device. */
|
||||||
|
const unsigned long paMacCore_FailIfConversionRequired = 0x02;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here are some "preset" combinations of flags (above) to get to some
|
||||||
|
* common configurations. THIS IS OVERKILL, but if more flags are added
|
||||||
|
* it won't be.
|
||||||
|
*/
|
||||||
|
/*This is the default setting: do as much sample rate conversion as possible
|
||||||
|
* and as little mucking with the device as possible. */
|
||||||
|
const unsigned long paMacCorePlayNice = 0x00;
|
||||||
|
/*This setting is tuned for pro audio apps. It allows SR conversion on input
|
||||||
|
and output, but it tries to set the appropriate SR on the device.*/
|
||||||
|
const unsigned long paMacCorePro = 0x01;
|
||||||
|
|
||||||
1934
portaudio-v19/pa_mac_core/pa_mac_core_auhal.c
Normal file
1934
portaudio-v19/pa_mac_core/pa_mac_core_auhal.c
Normal file
File diff suppressed because it is too large
Load Diff
907
portaudio-v19/pa_mac_core/pa_mac_core_old.c
Normal file
907
portaudio-v19/pa_mac_core/pa_mac_core_old.c
Normal file
@ -0,0 +1,907 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
* pa_mac_core.c
|
||||||
|
* Implementation of PortAudio for Mac OS X CoreAudio
|
||||||
|
*
|
||||||
|
* PortAudio Portable Real-Time Audio Library
|
||||||
|
* Latest Version at: http://www.portaudio.com
|
||||||
|
*
|
||||||
|
* Authors: Ross Bencina and Phil Burk
|
||||||
|
* 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 <CoreAudio/CoreAudio.h>
|
||||||
|
#include <AudioToolbox/AudioToolbox.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "portaudio.h"
|
||||||
|
#include "pa_trace.h"
|
||||||
|
#include "pa_util.h"
|
||||||
|
#include "pa_allocation.h"
|
||||||
|
#include "pa_hostapi.h"
|
||||||
|
#include "pa_stream.h"
|
||||||
|
#include "pa_cpuload.h"
|
||||||
|
#include "pa_process.h"
|
||||||
|
|
||||||
|
// ===== constants =====
|
||||||
|
|
||||||
|
// ===== structs =====
|
||||||
|
#pragma mark structs
|
||||||
|
|
||||||
|
// PaMacCoreHostApiRepresentation - host api datastructure specific to this implementation
|
||||||
|
typedef struct PaMacCore_HAR
|
||||||
|
{
|
||||||
|
PaUtilHostApiRepresentation inheritedHostApiRep;
|
||||||
|
PaUtilStreamInterface callbackStreamInterface;
|
||||||
|
PaUtilStreamInterface blockingStreamInterface;
|
||||||
|
|
||||||
|
PaUtilAllocationGroup *allocations;
|
||||||
|
AudioDeviceID *macCoreDeviceIds;
|
||||||
|
}
|
||||||
|
PaMacCoreHostApiRepresentation;
|
||||||
|
|
||||||
|
typedef struct PaMacCore_DI
|
||||||
|
{
|
||||||
|
PaDeviceInfo inheritedDeviceInfo;
|
||||||
|
}
|
||||||
|
PaMacCoreDeviceInfo;
|
||||||
|
|
||||||
|
// PaMacCoreStream - a stream data structure specifically for this implementation
|
||||||
|
typedef struct PaMacCore_S
|
||||||
|
{
|
||||||
|
PaUtilStreamRepresentation streamRepresentation;
|
||||||
|
PaUtilCpuLoadMeasurer cpuLoadMeasurer;
|
||||||
|
PaUtilBufferProcessor bufferProcessor;
|
||||||
|
|
||||||
|
int primeStreamUsingCallback;
|
||||||
|
|
||||||
|
AudioDeviceID inputDevice;
|
||||||
|
AudioDeviceID outputDevice;
|
||||||
|
|
||||||
|
// Processing thread management --------------
|
||||||
|
// HANDLE abortEvent;
|
||||||
|
// HANDLE processingThread;
|
||||||
|
// DWORD processingThreadId;
|
||||||
|
|
||||||
|
char throttleProcessingThreadOnOverload; // 0 -> don't throtte, non-0 -> throttle
|
||||||
|
int processingThreadPriority;
|
||||||
|
int highThreadPriority;
|
||||||
|
int throttledThreadPriority;
|
||||||
|
unsigned long throttledSleepMsecs;
|
||||||
|
|
||||||
|
int isStopped;
|
||||||
|
volatile int isActive;
|
||||||
|
volatile int stopProcessing; // stop thread once existing buffers have been returned
|
||||||
|
volatile int abortProcessing; // stop thread immediately
|
||||||
|
|
||||||
|
// DWORD allBuffersDurationMs; // used to calculate timeouts
|
||||||
|
}
|
||||||
|
PaMacCoreStream;
|
||||||
|
|
||||||
|
// Data needed by the CoreAudio callback functions
|
||||||
|
typedef struct PaMacCore_CD
|
||||||
|
{
|
||||||
|
PaMacCoreStream *stream;
|
||||||
|
PaStreamCallback *callback;
|
||||||
|
void *userData;
|
||||||
|
PaUtilConverter *inputConverter;
|
||||||
|
PaUtilConverter *outputConverter;
|
||||||
|
void *inputBuffer;
|
||||||
|
void *outputBuffer;
|
||||||
|
int inputChannelCount;
|
||||||
|
int outputChannelCount;
|
||||||
|
PaSampleFormat inputSampleFormat;
|
||||||
|
PaSampleFormat outputSampleFormat;
|
||||||
|
PaUtilTriangularDitherGenerator *ditherGenerator;
|
||||||
|
}
|
||||||
|
PaMacClientData;
|
||||||
|
|
||||||
|
// ===== CoreAudio-PortAudio bridge functions =====
|
||||||
|
#pragma mark CoreAudio-PortAudio bridge functions
|
||||||
|
|
||||||
|
// Maps CoreAudio OSStatus codes to PortAudio PaError codes
|
||||||
|
static PaError conv_err(OSStatus error)
|
||||||
|
{
|
||||||
|
PaError result;
|
||||||
|
|
||||||
|
switch (error) {
|
||||||
|
case kAudioHardwareNoError:
|
||||||
|
result = paNoError; break;
|
||||||
|
case kAudioHardwareNotRunningError:
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareUnspecifiedError:
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareUnknownPropertyError:
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareBadPropertySizeError:
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareIllegalOperationError:
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareBadDeviceError:
|
||||||
|
result = paInvalidDevice; break;
|
||||||
|
case kAudioHardwareBadStreamError:
|
||||||
|
result = paBadStreamPtr; break;
|
||||||
|
case kAudioHardwareUnsupportedOperationError:
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioDeviceUnsupportedFormatError:
|
||||||
|
result = paSampleFormatNotSupported; break;
|
||||||
|
case kAudioDevicePermissionsError:
|
||||||
|
result = paDeviceUnavailable; break;
|
||||||
|
default:
|
||||||
|
result = paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is unused
|
||||||
|
static AudioStreamBasicDescription *InitializeStreamDescription(const PaStreamParameters *parameters, double sampleRate)
|
||||||
|
{
|
||||||
|
struct AudioStreamBasicDescription *streamDescription = PaUtil_AllocateMemory(sizeof(AudioStreamBasicDescription));
|
||||||
|
streamDescription->mSampleRate = sampleRate;
|
||||||
|
streamDescription->mFormatID = kAudioFormatLinearPCM;
|
||||||
|
streamDescription->mFormatFlags = 0;
|
||||||
|
streamDescription->mFramesPerPacket = 1;
|
||||||
|
|
||||||
|
if (parameters->sampleFormat & paNonInterleaved) {
|
||||||
|
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsNonInterleaved;
|
||||||
|
streamDescription->mChannelsPerFrame = 1;
|
||||||
|
streamDescription->mBytesPerFrame = Pa_GetSampleSize(parameters->sampleFormat);
|
||||||
|
streamDescription->mBytesPerPacket = Pa_GetSampleSize(parameters->sampleFormat);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
streamDescription->mChannelsPerFrame = parameters->channelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
streamDescription->mBytesPerFrame = Pa_GetSampleSize(parameters->sampleFormat) * streamDescription->mChannelsPerFrame;
|
||||||
|
streamDescription->mBytesPerPacket = streamDescription->mBytesPerFrame * streamDescription->mFramesPerPacket;
|
||||||
|
|
||||||
|
if (parameters->sampleFormat & paFloat32) {
|
||||||
|
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsFloat;
|
||||||
|
streamDescription->mBitsPerChannel = 32;
|
||||||
|
}
|
||||||
|
else if (parameters->sampleFormat & paInt32) {
|
||||||
|
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||||
|
streamDescription->mBitsPerChannel = 32;
|
||||||
|
}
|
||||||
|
else if (parameters->sampleFormat & paInt24) {
|
||||||
|
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||||
|
streamDescription->mBitsPerChannel = 24;
|
||||||
|
}
|
||||||
|
else if (parameters->sampleFormat & paInt16) {
|
||||||
|
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||||
|
streamDescription->mBitsPerChannel = 16;
|
||||||
|
}
|
||||||
|
else if (parameters->sampleFormat & paInt8) {
|
||||||
|
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||||
|
streamDescription->mBitsPerChannel = 8;
|
||||||
|
}
|
||||||
|
else if (parameters->sampleFormat & paInt32) {
|
||||||
|
streamDescription->mBitsPerChannel = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return streamDescription;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static PaStreamCallbackTimeInfo *InitializeTimeInfo(const AudioTimeStamp* now, const AudioTimeStamp* inputTime, const AudioTimeStamp* outputTime)
|
||||||
|
{
|
||||||
|
PaStreamCallbackTimeInfo *timeInfo = PaUtil_AllocateMemory(sizeof(PaStreamCallbackTimeInfo));
|
||||||
|
|
||||||
|
timeInfo->inputBufferAdcTime = inputTime->mSampleTime;
|
||||||
|
timeInfo->currentTime = now->mSampleTime;
|
||||||
|
timeInfo->outputBufferDacTime = outputTime->mSampleTime;
|
||||||
|
|
||||||
|
return timeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== support functions =====
|
||||||
|
#pragma mark support functions
|
||||||
|
|
||||||
|
static void CleanUp(PaMacCoreHostApiRepresentation *macCoreHostApi)
|
||||||
|
{
|
||||||
|
if( macCoreHostApi->allocations )
|
||||||
|
{
|
||||||
|
PaUtil_FreeAllAllocations( macCoreHostApi->allocations );
|
||||||
|
PaUtil_DestroyAllocationGroup( macCoreHostApi->allocations );
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_FreeMemory( macCoreHostApi );
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError GetChannelInfo(PaDeviceInfo *deviceInfo, AudioDeviceID macCoreDeviceId, int isInput)
|
||||||
|
{
|
||||||
|
UInt32 propSize;
|
||||||
|
PaError err = paNoError;
|
||||||
|
UInt32 i;
|
||||||
|
int numChannels = 0;
|
||||||
|
AudioBufferList *buflist;
|
||||||
|
|
||||||
|
err = conv_err(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, NULL));
|
||||||
|
buflist = PaUtil_AllocateMemory(propSize);
|
||||||
|
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist));
|
||||||
|
if (!err) {
|
||||||
|
for (i = 0; i < buflist->mNumberBuffers; ++i) {
|
||||||
|
numChannels += buflist->mBuffers[i].mNumberChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInput)
|
||||||
|
deviceInfo->maxInputChannels = numChannels;
|
||||||
|
else
|
||||||
|
deviceInfo->maxOutputChannels = numChannels;
|
||||||
|
|
||||||
|
int frameLatency;
|
||||||
|
propSize = sizeof(UInt32);
|
||||||
|
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyLatency, &propSize, &frameLatency));
|
||||||
|
if (!err) {
|
||||||
|
double secondLatency = frameLatency / deviceInfo->defaultSampleRate;
|
||||||
|
if (isInput) {
|
||||||
|
deviceInfo->defaultLowInputLatency = secondLatency;
|
||||||
|
deviceInfo->defaultHighInputLatency = secondLatency;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deviceInfo->defaultLowOutputLatency = secondLatency;
|
||||||
|
deviceInfo->defaultHighOutputLatency = secondLatency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PaUtil_FreeMemory(buflist);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError InitializeDeviceInfo(PaMacCoreDeviceInfo *macCoreDeviceInfo, AudioDeviceID macCoreDeviceId, PaHostApiIndex hostApiIndex )
|
||||||
|
{
|
||||||
|
PaDeviceInfo *deviceInfo = &macCoreDeviceInfo->inheritedDeviceInfo;
|
||||||
|
deviceInfo->structVersion = 2;
|
||||||
|
deviceInfo->hostApi = hostApiIndex;
|
||||||
|
|
||||||
|
PaError err = paNoError;
|
||||||
|
UInt32 propSize;
|
||||||
|
|
||||||
|
err = conv_err(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL));
|
||||||
|
// FIXME: this allocation should be part of the allocations group
|
||||||
|
char *name = PaUtil_AllocateMemory(propSize);
|
||||||
|
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name));
|
||||||
|
if (!err) {
|
||||||
|
deviceInfo->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float64 sampleRate;
|
||||||
|
propSize = sizeof(Float64);
|
||||||
|
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &sampleRate));
|
||||||
|
if (!err) {
|
||||||
|
deviceInfo->defaultSampleRate = sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get channel info
|
||||||
|
err = GetChannelInfo(deviceInfo, macCoreDeviceId, 1);
|
||||||
|
err = GetChannelInfo(deviceInfo, macCoreDeviceId, 0);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError InitializeDeviceInfos( PaMacCoreHostApiRepresentation *macCoreHostApi, PaHostApiIndex hostApiIndex )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaUtilHostApiRepresentation *hostApi;
|
||||||
|
PaMacCoreDeviceInfo *deviceInfoArray;
|
||||||
|
|
||||||
|
// initialise device counts and default devices under the assumption that there are no devices. These values are incremented below if and when devices are successfully initialized.
|
||||||
|
hostApi = &macCoreHostApi->inheritedHostApiRep;
|
||||||
|
hostApi->info.deviceCount = 0;
|
||||||
|
hostApi->info.defaultInputDevice = paNoDevice;
|
||||||
|
hostApi->info.defaultOutputDevice = paNoDevice;
|
||||||
|
|
||||||
|
UInt32 propsize;
|
||||||
|
AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &propsize, NULL);
|
||||||
|
int numDevices = propsize / sizeof(AudioDeviceID);
|
||||||
|
hostApi->info.deviceCount = numDevices;
|
||||||
|
if (numDevices > 0) {
|
||||||
|
hostApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
|
||||||
|
macCoreHostApi->allocations, sizeof(PaDeviceInfo*) * numDevices );
|
||||||
|
if( !hostApi->deviceInfos )
|
||||||
|
{
|
||||||
|
return paInsufficientMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate all device info structs in a contiguous block
|
||||||
|
deviceInfoArray = (PaMacCoreDeviceInfo*)PaUtil_GroupAllocateMemory(
|
||||||
|
macCoreHostApi->allocations, sizeof(PaMacCoreDeviceInfo) * numDevices );
|
||||||
|
if( !deviceInfoArray )
|
||||||
|
{
|
||||||
|
return paInsufficientMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
macCoreHostApi->macCoreDeviceIds = PaUtil_GroupAllocateMemory(macCoreHostApi->allocations, propsize);
|
||||||
|
AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &propsize, macCoreHostApi->macCoreDeviceIds);
|
||||||
|
|
||||||
|
AudioDeviceID defaultInputDevice, defaultOutputDevice;
|
||||||
|
propsize = sizeof(AudioDeviceID);
|
||||||
|
AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propsize, &defaultInputDevice);
|
||||||
|
AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &propsize, &defaultOutputDevice);
|
||||||
|
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < numDevices; ++i) {
|
||||||
|
if (macCoreHostApi->macCoreDeviceIds[i] == defaultInputDevice) {
|
||||||
|
hostApi->info.defaultInputDevice = i;
|
||||||
|
}
|
||||||
|
if (macCoreHostApi->macCoreDeviceIds[i] == defaultOutputDevice) {
|
||||||
|
hostApi->info.defaultOutputDevice = i;
|
||||||
|
}
|
||||||
|
InitializeDeviceInfo(&deviceInfoArray[i], macCoreHostApi->macCoreDeviceIds[i], hostApiIndex);
|
||||||
|
hostApi->deviceInfos[i] = &(deviceInfoArray[i].inheritedDeviceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus CheckFormat(AudioDeviceID macCoreDeviceId, const PaStreamParameters *parameters, double sampleRate, int isInput)
|
||||||
|
{
|
||||||
|
UInt32 propSize = sizeof(AudioStreamBasicDescription);
|
||||||
|
AudioStreamBasicDescription *streamDescription = PaUtil_AllocateMemory(propSize);
|
||||||
|
|
||||||
|
streamDescription->mSampleRate = sampleRate;
|
||||||
|
streamDescription->mFormatID = 0;
|
||||||
|
streamDescription->mFormatFlags = 0;
|
||||||
|
streamDescription->mBytesPerPacket = 0;
|
||||||
|
streamDescription->mFramesPerPacket = 0;
|
||||||
|
streamDescription->mBytesPerFrame = 0;
|
||||||
|
streamDescription->mChannelsPerFrame = 0;
|
||||||
|
streamDescription->mBitsPerChannel = 0;
|
||||||
|
streamDescription->mReserved = 0;
|
||||||
|
|
||||||
|
OSStatus result = AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamFormatSupported, &propSize, streamDescription);
|
||||||
|
PaUtil_FreeMemory(streamDescription);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus CopyInputData(PaMacClientData* destination, const AudioBufferList *source, unsigned long frameCount)
|
||||||
|
{
|
||||||
|
int frameSpacing, channelSpacing;
|
||||||
|
if (destination->inputSampleFormat & paNonInterleaved) {
|
||||||
|
frameSpacing = 1;
|
||||||
|
channelSpacing = destination->inputChannelCount;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
frameSpacing = destination->inputChannelCount;
|
||||||
|
channelSpacing = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioBuffer const *inputBuffer = &source->mBuffers[0];
|
||||||
|
void *coreAudioBuffer = inputBuffer->mData;
|
||||||
|
void *portAudioBuffer = destination->inputBuffer;
|
||||||
|
UInt32 i, streamNumber, streamChannel;
|
||||||
|
for (i = streamNumber = streamChannel = 0; i < destination->inputChannelCount; ++i, ++streamChannel) {
|
||||||
|
if (streamChannel >= inputBuffer->mNumberChannels) {
|
||||||
|
++streamNumber;
|
||||||
|
inputBuffer = &source->mBuffers[streamNumber];
|
||||||
|
coreAudioBuffer = inputBuffer->mData;
|
||||||
|
streamChannel = 0;
|
||||||
|
}
|
||||||
|
destination->inputConverter(portAudioBuffer, frameSpacing, coreAudioBuffer, inputBuffer->mNumberChannels, frameCount, destination->ditherGenerator);
|
||||||
|
coreAudioBuffer += sizeof(Float32);
|
||||||
|
portAudioBuffer += Pa_GetSampleSize(destination->inputSampleFormat) * channelSpacing;
|
||||||
|
}
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus CopyOutputData(AudioBufferList* destination, PaMacClientData *source, unsigned long frameCount)
|
||||||
|
{
|
||||||
|
int frameSpacing, channelSpacing;
|
||||||
|
if (source->outputSampleFormat & paNonInterleaved) {
|
||||||
|
frameSpacing = 1;
|
||||||
|
channelSpacing = source->outputChannelCount;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
frameSpacing = source->outputChannelCount;
|
||||||
|
channelSpacing = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioBuffer *outputBuffer = &destination->mBuffers[0];
|
||||||
|
void *coreAudioBuffer = outputBuffer->mData;
|
||||||
|
void *portAudioBuffer = source->outputBuffer;
|
||||||
|
UInt32 i, streamNumber, streamChannel;
|
||||||
|
for (i = streamNumber = streamChannel = 0; i < source->outputChannelCount; ++i, ++streamChannel) {
|
||||||
|
if (streamChannel >= outputBuffer->mNumberChannels) {
|
||||||
|
++streamNumber;
|
||||||
|
outputBuffer = &destination->mBuffers[streamNumber];
|
||||||
|
coreAudioBuffer = outputBuffer->mData;
|
||||||
|
streamChannel = 0;
|
||||||
|
}
|
||||||
|
source->outputConverter(coreAudioBuffer, outputBuffer->mNumberChannels, portAudioBuffer, frameSpacing, frameCount, NULL);
|
||||||
|
coreAudioBuffer += sizeof(Float32);
|
||||||
|
portAudioBuffer += Pa_GetSampleSize(source->outputSampleFormat) * channelSpacing;
|
||||||
|
}
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus AudioIOProc( AudioDeviceID inDevice,
|
||||||
|
const AudioTimeStamp* inNow,
|
||||||
|
const AudioBufferList* inInputData,
|
||||||
|
const AudioTimeStamp* inInputTime,
|
||||||
|
AudioBufferList* outOutputData,
|
||||||
|
const AudioTimeStamp* inOutputTime,
|
||||||
|
void* inClientData)
|
||||||
|
{
|
||||||
|
PaMacClientData *clientData = (PaMacClientData *)inClientData;
|
||||||
|
PaStreamCallbackTimeInfo *timeInfo = InitializeTimeInfo(inNow, inInputTime, inOutputTime);
|
||||||
|
|
||||||
|
PaUtil_BeginCpuLoadMeasurement( &clientData->stream->cpuLoadMeasurer );
|
||||||
|
|
||||||
|
AudioBuffer *outputBuffer = &outOutputData->mBuffers[0];
|
||||||
|
unsigned long frameCount = outputBuffer->mDataByteSize / (outputBuffer->mNumberChannels * sizeof(Float32));
|
||||||
|
|
||||||
|
if (clientData->inputBuffer) {
|
||||||
|
CopyInputData(clientData, inInputData, frameCount);
|
||||||
|
}
|
||||||
|
PaStreamCallbackResult result = clientData->callback(clientData->inputBuffer, clientData->outputBuffer, frameCount, timeInfo, paNoFlag, clientData->userData);
|
||||||
|
if (clientData->outputBuffer) {
|
||||||
|
CopyOutputData(outOutputData, clientData, frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_EndCpuLoadMeasurement( &clientData->stream->cpuLoadMeasurer, frameCount );
|
||||||
|
|
||||||
|
if (result == paComplete || result == paAbort) {
|
||||||
|
Pa_StopStream(clientData->stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
PaUtil_FreeMemory( timeInfo );
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not for input-only streams, this is for streams where the input device is different from the output device
|
||||||
|
static OSStatus AudioInputProc( AudioDeviceID inDevice,
|
||||||
|
const AudioTimeStamp* inNow,
|
||||||
|
const AudioBufferList* inInputData,
|
||||||
|
const AudioTimeStamp* inInputTime,
|
||||||
|
AudioBufferList* outOutputData,
|
||||||
|
const AudioTimeStamp* inOutputTime,
|
||||||
|
void* inClientData)
|
||||||
|
{
|
||||||
|
PaMacClientData *clientData = (PaMacClientData *)inClientData;
|
||||||
|
PaStreamCallbackTimeInfo *timeInfo = InitializeTimeInfo(inNow, inInputTime, inOutputTime);
|
||||||
|
|
||||||
|
PaUtil_BeginCpuLoadMeasurement( &clientData->stream->cpuLoadMeasurer );
|
||||||
|
|
||||||
|
AudioBuffer const *inputBuffer = &inInputData->mBuffers[0];
|
||||||
|
unsigned long frameCount = inputBuffer->mDataByteSize / (inputBuffer->mNumberChannels * sizeof(Float32));
|
||||||
|
|
||||||
|
CopyInputData(clientData, inInputData, frameCount);
|
||||||
|
PaStreamCallbackResult result = clientData->callback(clientData->inputBuffer, clientData->outputBuffer, frameCount, timeInfo, paNoFlag, clientData->userData);
|
||||||
|
|
||||||
|
PaUtil_EndCpuLoadMeasurement( &clientData->stream->cpuLoadMeasurer, frameCount );
|
||||||
|
if( result == paComplete || result == paAbort )
|
||||||
|
Pa_StopStream(clientData->stream);
|
||||||
|
PaUtil_FreeMemory( timeInfo );
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not for output-only streams, this is for streams where the input device is different from the output device
|
||||||
|
static OSStatus AudioOutputProc( AudioDeviceID inDevice,
|
||||||
|
const AudioTimeStamp* inNow,
|
||||||
|
const AudioBufferList* inInputData,
|
||||||
|
const AudioTimeStamp* inInputTime,
|
||||||
|
AudioBufferList* outOutputData,
|
||||||
|
const AudioTimeStamp* inOutputTime,
|
||||||
|
void* inClientData)
|
||||||
|
{
|
||||||
|
PaMacClientData *clientData = (PaMacClientData *)inClientData;
|
||||||
|
//PaStreamCallbackTimeInfo *timeInfo = InitializeTimeInfo(inNow, inInputTime, inOutputTime);
|
||||||
|
|
||||||
|
PaUtil_BeginCpuLoadMeasurement( &clientData->stream->cpuLoadMeasurer );
|
||||||
|
|
||||||
|
AudioBuffer *outputBuffer = &outOutputData->mBuffers[0];
|
||||||
|
unsigned long frameCount = outputBuffer->mDataByteSize / (outputBuffer->mNumberChannels * sizeof(Float32));
|
||||||
|
|
||||||
|
//clientData->callback(NULL, clientData->outputBuffer, frameCount, timeInfo, paNoFlag, clientData->userData);
|
||||||
|
|
||||||
|
CopyOutputData(outOutputData, clientData, frameCount);
|
||||||
|
|
||||||
|
PaUtil_EndCpuLoadMeasurement( &clientData->stream->cpuLoadMeasurer, frameCount );
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError SetSampleRate(AudioDeviceID device, double sampleRate, int isInput)
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
|
||||||
|
double actualSampleRate;
|
||||||
|
UInt32 propSize = sizeof(double);
|
||||||
|
result = conv_err(AudioDeviceSetProperty(device, NULL, 0, isInput, kAudioDevicePropertyNominalSampleRate, propSize, &sampleRate));
|
||||||
|
|
||||||
|
result = conv_err(AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyNominalSampleRate, &propSize, &actualSampleRate));
|
||||||
|
|
||||||
|
if (result == paNoError && actualSampleRate != sampleRate) {
|
||||||
|
result = paInvalidSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError SetFramesPerBuffer(AudioDeviceID device, unsigned long framesPerBuffer, int isInput)
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
UInt32 preferredFramesPerBuffer = framesPerBuffer;
|
||||||
|
// while (preferredFramesPerBuffer > UINT32_MAX) {
|
||||||
|
// preferredFramesPerBuffer /= 2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
UInt32 actualFramesPerBuffer;
|
||||||
|
UInt32 propSize = sizeof(UInt32);
|
||||||
|
result = conv_err(AudioDeviceSetProperty(device, NULL, 0, isInput, kAudioDevicePropertyBufferFrameSize, propSize, &preferredFramesPerBuffer));
|
||||||
|
|
||||||
|
result = conv_err(AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyBufferFrameSize, &propSize, &actualFramesPerBuffer));
|
||||||
|
|
||||||
|
if (result != paNoError) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else if (actualFramesPerBuffer > framesPerBuffer) {
|
||||||
|
result = paBufferTooSmall;
|
||||||
|
}
|
||||||
|
else if (actualFramesPerBuffer < framesPerBuffer) {
|
||||||
|
result = paBufferTooBig;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError SetUpUnidirectionalStream(AudioDeviceID device, double sampleRate, unsigned long framesPerBuffer, int isInput)
|
||||||
|
{
|
||||||
|
PaError err = paNoError;
|
||||||
|
err = SetSampleRate(device, sampleRate, isInput);
|
||||||
|
if( err == paNoError )
|
||||||
|
err = SetFramesPerBuffer(device, framesPerBuffer, isInput);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== PortAudio functions =====
|
||||||
|
#pragma mark PortAudio functions
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
|
||||||
|
{
|
||||||
|
PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation*)hostApi;
|
||||||
|
|
||||||
|
CleanUp(macCoreHostApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate )
|
||||||
|
{
|
||||||
|
PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation*)hostApi;
|
||||||
|
PaDeviceInfo *deviceInfo;
|
||||||
|
|
||||||
|
PaError result = paNoError;
|
||||||
|
if (inputParameters) {
|
||||||
|
deviceInfo = macCoreHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device];
|
||||||
|
if (inputParameters->channelCount > deviceInfo->maxInputChannels)
|
||||||
|
result = paInvalidChannelCount;
|
||||||
|
else if (CheckFormat(macCoreHostApi->macCoreDeviceIds[inputParameters->device], inputParameters, sampleRate, 1) != kAudioHardwareNoError) {
|
||||||
|
result = paInvalidSampleRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputParameters && result == paNoError) {
|
||||||
|
deviceInfo = macCoreHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device];
|
||||||
|
if (outputParameters->channelCount > deviceInfo->maxOutputChannels)
|
||||||
|
result = paInvalidChannelCount;
|
||||||
|
else if (CheckFormat(macCoreHostApi->macCoreDeviceIds[outputParameters->device], outputParameters, sampleRate, 0) != kAudioHardwareNoError) {
|
||||||
|
result = paInvalidSampleRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
PaStream** s,
|
||||||
|
const PaStreamParameters *inputParameters,
|
||||||
|
const PaStreamParameters *outputParameters,
|
||||||
|
double sampleRate,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
PaStreamFlags streamFlags,
|
||||||
|
PaStreamCallback *streamCallback,
|
||||||
|
void *userData )
|
||||||
|
{
|
||||||
|
PaError err = paNoError;
|
||||||
|
PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation *)hostApi;
|
||||||
|
PaMacCoreStream *stream = PaUtil_AllocateMemory(sizeof(PaMacCoreStream));
|
||||||
|
stream->isActive = 0;
|
||||||
|
stream->isStopped = 1;
|
||||||
|
stream->inputDevice = kAudioDeviceUnknown;
|
||||||
|
stream->outputDevice = kAudioDeviceUnknown;
|
||||||
|
|
||||||
|
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
|
||||||
|
( (streamCallback)
|
||||||
|
? &macCoreHostApi->callbackStreamInterface
|
||||||
|
: &macCoreHostApi->blockingStreamInterface ),
|
||||||
|
streamCallback, userData );
|
||||||
|
PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
|
||||||
|
|
||||||
|
*s = (PaStream*)stream;
|
||||||
|
PaMacClientData *clientData = PaUtil_AllocateMemory(sizeof(PaMacClientData));
|
||||||
|
clientData->stream = stream;
|
||||||
|
clientData->callback = streamCallback;
|
||||||
|
clientData->userData = userData;
|
||||||
|
clientData->inputBuffer = 0;
|
||||||
|
clientData->outputBuffer = 0;
|
||||||
|
clientData->ditherGenerator = PaUtil_AllocateMemory(sizeof(PaUtilTriangularDitherGenerator));
|
||||||
|
PaUtil_InitializeTriangularDitherState(clientData->ditherGenerator);
|
||||||
|
|
||||||
|
if (inputParameters != NULL) {
|
||||||
|
stream->inputDevice = macCoreHostApi->macCoreDeviceIds[inputParameters->device];
|
||||||
|
clientData->inputConverter = PaUtil_SelectConverter(paFloat32, inputParameters->sampleFormat, streamFlags);
|
||||||
|
clientData->inputBuffer = PaUtil_AllocateMemory(Pa_GetSampleSize(inputParameters->sampleFormat) * framesPerBuffer * inputParameters->channelCount);
|
||||||
|
clientData->inputChannelCount = inputParameters->channelCount;
|
||||||
|
clientData->inputSampleFormat = inputParameters->sampleFormat;
|
||||||
|
err = SetUpUnidirectionalStream(stream->inputDevice, sampleRate, framesPerBuffer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == paNoError && outputParameters != NULL) {
|
||||||
|
stream->outputDevice = macCoreHostApi->macCoreDeviceIds[outputParameters->device];
|
||||||
|
clientData->outputConverter = PaUtil_SelectConverter(outputParameters->sampleFormat, paFloat32, streamFlags);
|
||||||
|
clientData->outputBuffer = PaUtil_AllocateMemory(Pa_GetSampleSize(outputParameters->sampleFormat) * framesPerBuffer * outputParameters->channelCount);
|
||||||
|
clientData->outputChannelCount = outputParameters->channelCount;
|
||||||
|
clientData->outputSampleFormat = outputParameters->sampleFormat;
|
||||||
|
err = SetUpUnidirectionalStream(stream->outputDevice, sampleRate, framesPerBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputParameters == NULL || outputParameters == NULL || stream->inputDevice == stream->outputDevice) {
|
||||||
|
AudioDeviceID device = (inputParameters == NULL) ? stream->outputDevice : stream->inputDevice;
|
||||||
|
|
||||||
|
AudioDeviceAddIOProc(device, AudioIOProc, clientData);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// using different devices for input and output
|
||||||
|
AudioDeviceAddIOProc(stream->inputDevice, AudioInputProc, clientData);
|
||||||
|
AudioDeviceAddIOProc(stream->outputDevice, AudioOutputProc, clientData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: When CloseStream() is called, the multi-api layer ensures that the stream has already been stopped or aborted.
|
||||||
|
static PaError CloseStream( PaStream* s )
|
||||||
|
{
|
||||||
|
PaError err = paNoError;
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
PaUtil_ResetCpuLoadMeasurer( &stream->cpuLoadMeasurer );
|
||||||
|
|
||||||
|
if (stream->inputDevice != kAudioDeviceUnknown) {
|
||||||
|
if (stream->outputDevice == kAudioDeviceUnknown || stream->outputDevice == stream->inputDevice) {
|
||||||
|
err = conv_err(AudioDeviceRemoveIOProc(stream->inputDevice, AudioIOProc));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = conv_err(AudioDeviceRemoveIOProc(stream->inputDevice, AudioInputProc));
|
||||||
|
err = conv_err(AudioDeviceRemoveIOProc(stream->outputDevice, AudioOutputProc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = conv_err(AudioDeviceRemoveIOProc(stream->outputDevice, AudioIOProc));
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError StartStream( PaStream *s )
|
||||||
|
{
|
||||||
|
PaError err = paNoError;
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
if (stream->inputDevice != kAudioDeviceUnknown) {
|
||||||
|
if (stream->outputDevice == kAudioDeviceUnknown || stream->outputDevice == stream->inputDevice) {
|
||||||
|
err = conv_err(AudioDeviceStart(stream->inputDevice, AudioIOProc));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = conv_err(AudioDeviceStart(stream->inputDevice, AudioInputProc));
|
||||||
|
err = conv_err(AudioDeviceStart(stream->outputDevice, AudioOutputProc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = conv_err(AudioDeviceStart(stream->outputDevice, AudioIOProc));
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->isActive = 1;
|
||||||
|
stream->isStopped = 0;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError AbortStream( PaStream *s )
|
||||||
|
{
|
||||||
|
PaError err = paNoError;
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
if (stream->inputDevice != kAudioDeviceUnknown) {
|
||||||
|
if (stream->outputDevice == kAudioDeviceUnknown || stream->outputDevice == stream->inputDevice) {
|
||||||
|
err = conv_err(AudioDeviceStop(stream->inputDevice, AudioIOProc));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = conv_err(AudioDeviceStop(stream->inputDevice, AudioInputProc));
|
||||||
|
err = conv_err(AudioDeviceStop(stream->outputDevice, AudioOutputProc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = conv_err(AudioDeviceStop(stream->outputDevice, AudioIOProc));
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->isActive = 0;
|
||||||
|
stream->isStopped = 1;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError StopStream( PaStream *s )
|
||||||
|
{
|
||||||
|
// TODO: this should be nicer than abort
|
||||||
|
return AbortStream(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PaError IsStreamStopped( PaStream *s )
|
||||||
|
{
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
return stream->isStopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError IsStreamActive( PaStream *s )
|
||||||
|
{
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
return stream->isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaTime GetStreamTime( PaStream *s )
|
||||||
|
{
|
||||||
|
OSStatus err;
|
||||||
|
PaTime result;
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
AudioTimeStamp *timeStamp = PaUtil_AllocateMemory(sizeof(AudioTimeStamp));
|
||||||
|
if (stream->inputDevice != kAudioDeviceUnknown) {
|
||||||
|
err = AudioDeviceGetCurrentTime(stream->inputDevice, timeStamp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = AudioDeviceGetCurrentTime(stream->outputDevice, timeStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = err ? 0 : timeStamp->mSampleTime;
|
||||||
|
PaUtil_FreeMemory(timeStamp);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static double GetStreamCpuLoad( PaStream* s )
|
||||||
|
{
|
||||||
|
PaMacCoreStream *stream = (PaMacCoreStream*)s;
|
||||||
|
|
||||||
|
return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// As separate stream interfaces are used for blocking and callback streams, the following functions can be guaranteed to only be called for blocking streams.
|
||||||
|
|
||||||
|
static PaError ReadStream( PaStream* s,
|
||||||
|
void *buffer,
|
||||||
|
unsigned long frames )
|
||||||
|
{
|
||||||
|
return paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PaError WriteStream( PaStream* s,
|
||||||
|
const void *buffer,
|
||||||
|
unsigned long frames )
|
||||||
|
{
|
||||||
|
return paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static signed long GetStreamReadAvailable( PaStream* s )
|
||||||
|
{
|
||||||
|
return paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static signed long GetStreamWriteAvailable( PaStream* s )
|
||||||
|
{
|
||||||
|
return paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HostAPI-specific initialization function
|
||||||
|
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation *)PaUtil_AllocateMemory( sizeof(PaMacCoreHostApiRepresentation) );
|
||||||
|
if( !macCoreHostApi )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
macCoreHostApi->allocations = PaUtil_CreateAllocationGroup();
|
||||||
|
if( !macCoreHostApi->allocations )
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hostApi = &macCoreHostApi->inheritedHostApiRep;
|
||||||
|
(*hostApi)->info.structVersion = 1;
|
||||||
|
(*hostApi)->info.type = paCoreAudio;
|
||||||
|
(*hostApi)->info.name = "CoreAudio";
|
||||||
|
|
||||||
|
result = InitializeDeviceInfos(macCoreHostApi, hostApiIndex);
|
||||||
|
if (result != paNoError) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the proper callbacks to this HostApi's functions
|
||||||
|
(*hostApi)->Terminate = Terminate;
|
||||||
|
(*hostApi)->OpenStream = OpenStream;
|
||||||
|
(*hostApi)->IsFormatSupported = IsFormatSupported;
|
||||||
|
|
||||||
|
PaUtil_InitializeStreamInterface( &macCoreHostApi->callbackStreamInterface, CloseStream, StartStream,
|
||||||
|
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
|
||||||
|
GetStreamTime, GetStreamCpuLoad,
|
||||||
|
PaUtil_DummyRead, PaUtil_DummyWrite,
|
||||||
|
PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
|
||||||
|
|
||||||
|
PaUtil_InitializeStreamInterface( &macCoreHostApi->blockingStreamInterface, CloseStream, StartStream,
|
||||||
|
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
|
||||||
|
GetStreamTime, PaUtil_DummyGetCpuLoad,
|
||||||
|
ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if( macCoreHostApi ) {
|
||||||
|
CleanUp(macCoreHostApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
466
portaudio-v19/pa_mac_core/pa_mac_core_utilities.c
Normal file
466
portaudio-v19/pa_mac_core/pa_mac_core_utilities.c
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* pa_mac_core_utilities.c
|
||||||
|
*
|
||||||
|
* utilitiy functions for pa_mac_core.c
|
||||||
|
*
|
||||||
|
* This functions are more like helper functions than part of the core,
|
||||||
|
* so I moved them to a separate file so the core code would be cleaner.
|
||||||
|
*
|
||||||
|
* by Bjorn Roche.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Translates MacOS generated errors into PaErrors
|
||||||
|
*/
|
||||||
|
static PaError PaMacCore_SetError(OSStatus error, int line, int isError)
|
||||||
|
{
|
||||||
|
/*FIXME: still need to handle possible ComponentResult values.*/
|
||||||
|
/* unfortunately, they don't seem to be documented anywhere.*/
|
||||||
|
PaError result;
|
||||||
|
const char *errorType;
|
||||||
|
const char *errorText;
|
||||||
|
|
||||||
|
switch (error) {
|
||||||
|
case kAudioHardwareNoError:
|
||||||
|
return paNoError;
|
||||||
|
case kAudioHardwareNotRunningError:
|
||||||
|
errorText = "Audio Hardware Not Running";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareUnspecifiedError:
|
||||||
|
errorText = "Unspecified Audio Hardware Error";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareUnknownPropertyError:
|
||||||
|
errorText = "Audio Hardware: Unknown Property";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareBadPropertySizeError:
|
||||||
|
errorText = "Audio Hardware: Bad Property Size";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareIllegalOperationError:
|
||||||
|
errorText = "Audio Hardware: Illegal Operation";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioHardwareBadDeviceError:
|
||||||
|
errorText = "Audio Hardware: Bad Device";
|
||||||
|
result = paInvalidDevice; break;
|
||||||
|
case kAudioHardwareBadStreamError:
|
||||||
|
errorText = "Audio Hardware: BadStream";
|
||||||
|
result = paBadStreamPtr; break;
|
||||||
|
case kAudioHardwareUnsupportedOperationError:
|
||||||
|
errorText = "Audio Hardware: Unsupported Operation";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioDeviceUnsupportedFormatError:
|
||||||
|
errorText = "Audio Device: Unsupported Format";
|
||||||
|
result = paSampleFormatNotSupported; break;
|
||||||
|
case kAudioDevicePermissionsError:
|
||||||
|
errorText = "Audio Device: Permissions Error";
|
||||||
|
result = paDeviceUnavailable; break;
|
||||||
|
/* Audio Unit Errors: http://developer.apple.com/documentation/MusicAudio/Reference/CoreAudio/audio_units/chapter_5_section_3.html */
|
||||||
|
case kAudioUnitErr_InvalidProperty:
|
||||||
|
errorText = "Audio Unit: Invalid Property";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_InvalidParameter:
|
||||||
|
errorText = "Audio Unit: Invalid Parameter";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_NoConnection:
|
||||||
|
errorText = "Audio Unit: No Connection";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_FailedInitialization:
|
||||||
|
errorText = "Audio Unit: Initialization Failed";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_TooManyFramesToProcess:
|
||||||
|
errorText = "Audio Unit: Too Many Frames";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_IllegalInstrument:
|
||||||
|
errorText = "Audio Unit: Illegal Instrument";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_InstrumentTypeNotFound:
|
||||||
|
errorText = "Audio Unit: Instrument Type Not Found";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_InvalidFile:
|
||||||
|
errorText = "Audio Unit: Invalid File";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_UnknownFileType:
|
||||||
|
errorText = "Audio Unit: Unknown File Type";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_FileNotSpecified:
|
||||||
|
errorText = "Audio Unit: File Not Specified";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_FormatNotSupported:
|
||||||
|
errorText = "Audio Unit: Format Not Supported";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_Uninitialized:
|
||||||
|
errorText = "Audio Unit: Unitialized";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_InvalidScope:
|
||||||
|
errorText = "Audio Unit: Invalid Scope";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_PropertyNotWritable:
|
||||||
|
errorText = "Audio Unit: PropertyNotWritable";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_InvalidPropertyValue:
|
||||||
|
errorText = "Audio Unit: Invalid Property Value";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_PropertyNotInUse:
|
||||||
|
errorText = "Audio Unit: Property Not In Use";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_Initialized:
|
||||||
|
errorText = "Audio Unit: Initialized";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_InvalidOfflineRender:
|
||||||
|
errorText = "Audio Unit: Invalid Offline Render";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_Unauthorized:
|
||||||
|
errorText = "Audio Unit: Unauthorized";
|
||||||
|
result = paInternalError; break;
|
||||||
|
case kAudioUnitErr_CannotDoInCurrentContext:
|
||||||
|
errorText = "Audio Unit: cannot do in current context";
|
||||||
|
result = paInternalError; break;
|
||||||
|
default:
|
||||||
|
errorText = "Unknown Error";
|
||||||
|
result = paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError)
|
||||||
|
errorType = "Error";
|
||||||
|
else
|
||||||
|
errorType = "Warning";
|
||||||
|
|
||||||
|
if ((int)error < -99999 || (int)error > 99999)
|
||||||
|
DBUG(("%s on line %d: err='%4s', msg='%s'\n", errorType, line, (const char *)&error, errorText));
|
||||||
|
else
|
||||||
|
DBUG(("%s on line %d: err=%d, 0x%x, msg='%s'\n", errorType, line, (int)error, (unsigned)error, errorText));
|
||||||
|
|
||||||
|
PaUtil_SetLastHostErrorInfo( paCoreAudio, error, errorText );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Durring testing of core audio, I found that serious crashes could occur
|
||||||
|
* if properties such as sample rate were changed multiple times in rapid
|
||||||
|
* succession. The function below has some fancy logic to make sure that changes
|
||||||
|
* are acknowledged before another is requested. That seems to help a lot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
typedef struct {
|
||||||
|
bool once; /* I didn't end up using this. bdr */
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
} MutexAndBool ;
|
||||||
|
|
||||||
|
static OSStatus propertyProc(
|
||||||
|
AudioDeviceID inDevice,
|
||||||
|
UInt32 inChannel,
|
||||||
|
Boolean isInput,
|
||||||
|
AudioDevicePropertyID inPropertyID,
|
||||||
|
void* inClientData )
|
||||||
|
{
|
||||||
|
MutexAndBool *mab = (MutexAndBool *) inClientData;
|
||||||
|
mab->once = TRUE;
|
||||||
|
pthread_mutex_unlock( &(mab->mutex) );
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sets the value of the given property and waits for the change to
|
||||||
|
be acknowledged, and returns the final value, which is not guaranteed
|
||||||
|
by this function to be the same as the desired value. Obviously, this
|
||||||
|
function can only be used for data whose input and output are the
|
||||||
|
same size and format, and their size and format are known in advance.*/
|
||||||
|
PaError AudioDeviceSetPropertyNowAndWaitForChange(
|
||||||
|
AudioDeviceID inDevice,
|
||||||
|
UInt32 inChannel,
|
||||||
|
Boolean isInput,
|
||||||
|
AudioDevicePropertyID inPropertyID,
|
||||||
|
UInt32 inPropertyDataSize,
|
||||||
|
const void *inPropertyData,
|
||||||
|
void *outPropertyData )
|
||||||
|
{
|
||||||
|
OSStatus macErr;
|
||||||
|
int unixErr;
|
||||||
|
MutexAndBool mab;
|
||||||
|
UInt32 outPropertyDataSize = inPropertyDataSize;
|
||||||
|
|
||||||
|
/* First, see if it already has that value. If so, return. */
|
||||||
|
macErr = AudioDeviceGetProperty( inDevice, inChannel,
|
||||||
|
isInput, inPropertyID,
|
||||||
|
&outPropertyDataSize, outPropertyData );
|
||||||
|
if( macErr )
|
||||||
|
goto failMac2;
|
||||||
|
if( inPropertyDataSize!=outPropertyDataSize )
|
||||||
|
return paInternalError;
|
||||||
|
if( 0==memcmp( outPropertyData, inPropertyData, outPropertyDataSize ) )
|
||||||
|
return paNoError;
|
||||||
|
|
||||||
|
/* setup and lock mutex */
|
||||||
|
mab.once = FALSE;
|
||||||
|
unixErr = pthread_mutex_init( &mab.mutex, NULL );
|
||||||
|
if( unixErr )
|
||||||
|
goto failUnix2;
|
||||||
|
unixErr = pthread_mutex_lock( &mab.mutex );
|
||||||
|
if( unixErr )
|
||||||
|
goto failUnix;
|
||||||
|
|
||||||
|
/* add property listener */
|
||||||
|
macErr = AudioDeviceAddPropertyListener( inDevice, inChannel, isInput,
|
||||||
|
inPropertyID, propertyProc,
|
||||||
|
&mab );
|
||||||
|
if( macErr )
|
||||||
|
goto failMac;
|
||||||
|
/* set property */
|
||||||
|
macErr = AudioDeviceSetProperty( inDevice, NULL, inChannel,
|
||||||
|
isInput, inPropertyID,
|
||||||
|
inPropertyDataSize, inPropertyData );
|
||||||
|
if( macErr ) {
|
||||||
|
/* we couldn't set the property, so we'll just unlock the mutex
|
||||||
|
and move on. */
|
||||||
|
pthread_mutex_unlock( &mab.mutex );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for property to change */
|
||||||
|
unixErr = pthread_mutex_lock( &mab.mutex );
|
||||||
|
if( unixErr )
|
||||||
|
goto failUnix;
|
||||||
|
|
||||||
|
/* now read the property back out */
|
||||||
|
macErr = AudioDeviceGetProperty( inDevice, inChannel,
|
||||||
|
isInput, inPropertyID,
|
||||||
|
&outPropertyDataSize, outPropertyData );
|
||||||
|
if( macErr )
|
||||||
|
goto failMac;
|
||||||
|
/* cleanup */
|
||||||
|
AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput,
|
||||||
|
inPropertyID, propertyProc );
|
||||||
|
unixErr = pthread_mutex_unlock( &mab.mutex );
|
||||||
|
if( unixErr )
|
||||||
|
goto failUnix2;
|
||||||
|
unixErr = pthread_mutex_destroy( &mab.mutex );
|
||||||
|
if( unixErr )
|
||||||
|
goto failUnix2;
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
|
||||||
|
failUnix:
|
||||||
|
pthread_mutex_destroy( &mab.mutex );
|
||||||
|
AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput,
|
||||||
|
inPropertyID, propertyProc );
|
||||||
|
|
||||||
|
failUnix2:
|
||||||
|
DBUG( ("Error #%d while setting a device property: %s\n", unixErr, strerror( unixErr ) ) );
|
||||||
|
return paUnanticipatedHostError;
|
||||||
|
|
||||||
|
failMac:
|
||||||
|
pthread_mutex_destroy( &mab.mutex );
|
||||||
|
AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput,
|
||||||
|
inPropertyID, propertyProc );
|
||||||
|
failMac2:
|
||||||
|
return ERR( macErr );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the sample rate the HAL device.
|
||||||
|
* if requireExact: set the sample rate or fail.
|
||||||
|
*
|
||||||
|
* otherwise : set the exact sample rate.
|
||||||
|
* If that fails, check for available sample rates, and choose one
|
||||||
|
* higher than the requested rate. If there isn't a higher one,
|
||||||
|
* just use the highest available.
|
||||||
|
*/
|
||||||
|
static PaError setBestSampleRateForDevice( const AudioDeviceID device,
|
||||||
|
const bool isOutput,
|
||||||
|
const bool requireExact,
|
||||||
|
const Float64 desiredSrate )
|
||||||
|
{
|
||||||
|
/*FIXME: changing the sample rate is disruptive to other programs using the
|
||||||
|
device, so it might be good to offer a custom flag to not change the
|
||||||
|
sample rate and just do conversion. (in my casual tests, there is
|
||||||
|
no disruption unless the sample rate really does need to change) */
|
||||||
|
const bool isInput = isOutput ? 0 : 1;
|
||||||
|
Float64 srate;
|
||||||
|
UInt32 propsize = sizeof( Float64 );
|
||||||
|
OSErr err;
|
||||||
|
AudioValueRange *ranges;
|
||||||
|
int i=0;
|
||||||
|
Float64 max = -1; /*the maximum rate available*/
|
||||||
|
Float64 best = -1; /*the lowest sample rate still greater than desired rate*/
|
||||||
|
VDBUG(("Setting sample rate for device %ld to %g.\n",device,(float)desiredSrate));
|
||||||
|
|
||||||
|
/* -- try setting the sample rate -- */
|
||||||
|
err = AudioDeviceSetPropertyNowAndWaitForChange(
|
||||||
|
device, 0, isInput,
|
||||||
|
kAudioDevicePropertyNominalSampleRate,
|
||||||
|
propsize, &desiredSrate, &srate );
|
||||||
|
if( err )
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* -- if the rate agrees, and we got no errors, we are done -- */
|
||||||
|
if( !err && srate == desiredSrate )
|
||||||
|
return paNoError;
|
||||||
|
/* -- we've failed if the rates disagree and we are setting input -- */
|
||||||
|
if( requireExact )
|
||||||
|
return paInvalidSampleRate;
|
||||||
|
|
||||||
|
/* -- generate a list of available sample rates -- */
|
||||||
|
err = AudioDeviceGetPropertyInfo( device, 0, isInput,
|
||||||
|
kAudioDevicePropertyAvailableNominalSampleRates,
|
||||||
|
&propsize, NULL );
|
||||||
|
if( err )
|
||||||
|
return ERR( err );
|
||||||
|
ranges = (AudioValueRange *)calloc( 1, propsize );
|
||||||
|
if( !ranges )
|
||||||
|
return paInsufficientMemory;
|
||||||
|
err = AudioDeviceGetProperty( device, 0, isInput,
|
||||||
|
kAudioDevicePropertyAvailableNominalSampleRates,
|
||||||
|
&propsize, ranges );
|
||||||
|
if( err )
|
||||||
|
{
|
||||||
|
free( ranges );
|
||||||
|
return ERR( err );
|
||||||
|
}
|
||||||
|
VDBUG(("Requested sample rate of %g was not available.\n", (float)desiredSrate));
|
||||||
|
VDBUG(("%lu Available Sample Rates are:\n",propsize/sizeof(AudioValueRange)));
|
||||||
|
#ifdef MAC_CORE_VERBOSE_DEBUG
|
||||||
|
for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
|
||||||
|
VDBUG( ("\t%g-%g\n",
|
||||||
|
(float) ranges[i].mMinimum,
|
||||||
|
(float) ranges[i].mMaximum ) );
|
||||||
|
#endif
|
||||||
|
VDBUG(("-----\n"));
|
||||||
|
|
||||||
|
/* -- now pick the best available sample rate -- */
|
||||||
|
for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
|
||||||
|
{
|
||||||
|
if( ranges[i].mMaximum > max ) max = ranges[i].mMaximum;
|
||||||
|
if( ranges[i].mMinimum > desiredSrate ) {
|
||||||
|
if( best < 0 )
|
||||||
|
best = ranges[i].mMinimum;
|
||||||
|
else if( ranges[i].mMinimum < best )
|
||||||
|
best = ranges[i].mMinimum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( best < 0 )
|
||||||
|
best = max;
|
||||||
|
VDBUG( ("Maximum Rate %g. best is %g.\n", max, best ) );
|
||||||
|
free( ranges );
|
||||||
|
|
||||||
|
/* -- set the sample rate -- */
|
||||||
|
propsize = sizeof( best );
|
||||||
|
err = AudioDeviceSetPropertyNowAndWaitForChange(
|
||||||
|
device, 0, isInput,
|
||||||
|
kAudioDevicePropertyNominalSampleRate,
|
||||||
|
propsize, &best, &srate );
|
||||||
|
if( err )
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
return ERR( err );
|
||||||
|
/* -- if the set rate matches, we are done -- */
|
||||||
|
if( srate == best )
|
||||||
|
return paNoError;
|
||||||
|
|
||||||
|
/* -- otherwise, something wierd happened: we didn't set the rate, and we got no errors. Just bail. */
|
||||||
|
return paInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Attempts to set the requestedFramesPerBuffer. If it can't set the exact
|
||||||
|
value, it settles for something smaller if available. If nothing smaller
|
||||||
|
is available, it uses the smallest available size.
|
||||||
|
actualFramesPerBuffer will be set to the actual value on successful return.
|
||||||
|
OK to pass NULL to actualFramesPerBuffer.
|
||||||
|
The logic is very simmilar too setBestSampleRate only failure here is
|
||||||
|
not usually catastrophic.
|
||||||
|
*/
|
||||||
|
static PaError setBestFramesPerBuffer( const AudioDeviceID device,
|
||||||
|
const bool isOutput,
|
||||||
|
unsigned long requestedFramesPerBuffer,
|
||||||
|
unsigned long *actualFramesPerBuffer )
|
||||||
|
{
|
||||||
|
UInt32 afpb;
|
||||||
|
const bool isInput = !isOutput;
|
||||||
|
UInt32 propsize = sizeof(UInt32);
|
||||||
|
OSErr err;
|
||||||
|
Float64 min = -1; /*the min blocksize*/
|
||||||
|
Float64 best = -1; /*the best blocksize*/
|
||||||
|
int i=0;
|
||||||
|
AudioValueRange *ranges;
|
||||||
|
|
||||||
|
if( actualFramesPerBuffer == NULL )
|
||||||
|
actualFramesPerBuffer = &afpb;
|
||||||
|
|
||||||
|
|
||||||
|
/* -- try and set exact FPB -- */
|
||||||
|
err = AudioDeviceSetProperty( device, NULL, 0, isInput,
|
||||||
|
kAudioDevicePropertyBufferFrameSize,
|
||||||
|
propsize, &requestedFramesPerBuffer);
|
||||||
|
err = AudioDeviceGetProperty( device, 0, isInput,
|
||||||
|
kAudioDevicePropertyBufferFrameSize,
|
||||||
|
&propsize, actualFramesPerBuffer);
|
||||||
|
if( err )
|
||||||
|
return ERR( err );
|
||||||
|
if( *actualFramesPerBuffer == requestedFramesPerBuffer )
|
||||||
|
return paNoError; /* we are done */
|
||||||
|
|
||||||
|
/* -- fetch available block sizes -- */
|
||||||
|
err = AudioDeviceGetPropertyInfo( device, 0, isInput,
|
||||||
|
kAudioDevicePropertyBufferSizeRange,
|
||||||
|
&propsize, NULL );
|
||||||
|
if( err )
|
||||||
|
return ERR( err );
|
||||||
|
ranges = (AudioValueRange *)calloc( 1, propsize );
|
||||||
|
if( !ranges )
|
||||||
|
return paInsufficientMemory;
|
||||||
|
err = AudioDeviceGetProperty( device, 0, isInput,
|
||||||
|
kAudioDevicePropertyBufferSizeRange,
|
||||||
|
&propsize, ranges );
|
||||||
|
if( err )
|
||||||
|
{
|
||||||
|
free( ranges );
|
||||||
|
return ERR( err );
|
||||||
|
}
|
||||||
|
VDBUG(("Requested block size of %lu was not available.\n",
|
||||||
|
requestedFramesPerBuffer ));
|
||||||
|
VDBUG(("%lu Available block sizes are:\n",propsize/sizeof(AudioValueRange)));
|
||||||
|
#ifdef MAC_CORE_VERBOSE_DEBUG
|
||||||
|
for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
|
||||||
|
VDBUG( ("\t%g-%g\n",
|
||||||
|
(float) ranges[i].mMinimum,
|
||||||
|
(float) ranges[i].mMaximum ) );
|
||||||
|
#endif
|
||||||
|
VDBUG(("-----\n"));
|
||||||
|
|
||||||
|
/* --- now pick the best available framesPerBuffer -- */
|
||||||
|
for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
|
||||||
|
{
|
||||||
|
if( min == -1 || ranges[i].mMinimum < min ) min = ranges[i].mMinimum;
|
||||||
|
if( ranges[i].mMaximum < requestedFramesPerBuffer ) {
|
||||||
|
if( best < 0 )
|
||||||
|
best = ranges[i].mMaximum;
|
||||||
|
else if( ranges[i].mMaximum > best )
|
||||||
|
best = ranges[i].mMaximum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( best == -1 )
|
||||||
|
best = min;
|
||||||
|
VDBUG( ("Minimum FPB %g. best is %g.\n", min, best ) );
|
||||||
|
free( ranges );
|
||||||
|
|
||||||
|
/* --- set the buffer size (ignore errors) -- */
|
||||||
|
requestedFramesPerBuffer = (UInt32) best ;
|
||||||
|
propsize = sizeof( UInt32 );
|
||||||
|
err = AudioDeviceSetProperty( device, NULL, 0, isInput,
|
||||||
|
kAudioDevicePropertyBufferSize,
|
||||||
|
propsize, &requestedFramesPerBuffer );
|
||||||
|
/* --- read the property to check that it was set -- */
|
||||||
|
err = AudioDeviceGetProperty( device, 0, isInput,
|
||||||
|
kAudioDevicePropertyBufferSize,
|
||||||
|
&propsize, actualFramesPerBuffer );
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
return ERR( err );
|
||||||
|
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
1656
portaudio-v19/pa_mac_sm/pa_mac_sm.c
Normal file
1656
portaudio-v19/pa_mac_sm/pa_mac_sm.c
Normal file
File diff suppressed because it is too large
Load Diff
1417
portaudio-v19/pa_sgi/pa_sgi.c
Normal file
1417
portaudio-v19/pa_sgi/pa_sgi.c
Normal file
File diff suppressed because it is too large
Load Diff
60
portaudio-v19/pa_tests/README.txt
Normal file
60
portaudio-v19/pa_tests/README.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
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
|
||||||
131
portaudio-v19/pa_tests/debug_convert.c
Normal file
131
portaudio-v19/pa_tests/debug_convert.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
55
portaudio-v19/pa_tests/debug_dither_calc.c
Normal file
55
portaudio-v19/pa_tests/debug_dither_calc.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* $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 );
|
||||||
|
}
|
||||||
183
portaudio-v19/pa_tests/debug_dual.c
Normal file
183
portaudio-v19/pa_tests/debug_dual.c
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
179
portaudio-v19/pa_tests/debug_multi_in.c
Normal file
179
portaudio-v19/pa_tests/debug_multi_in.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
144
portaudio-v19/pa_tests/debug_multi_out.c
Normal file
144
portaudio-v19/pa_tests/debug_multi_out.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
339
portaudio-v19/pa_tests/debug_record.c
Normal file
339
portaudio-v19/pa_tests/debug_record.c
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
351
portaudio-v19/pa_tests/debug_record_reuse.c
Normal file
351
portaudio-v19/pa_tests/debug_record_reuse.c
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user