mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-10-26 02:20:20 -04: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