mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-23 12:48:40 -05:00
- More remnants deleted of old portaudio-v19
They have done a major re-org of their directory structure git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/trunk@254 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
0981dc4123
commit
fe4de879ac
@ -1,186 +0,0 @@
|
|||||||
# 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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,198 +0,0 @@
|
|||||||
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")
|
|
@ -1,30 +0,0 @@
|
|||||||
# 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}
|
|
@ -1,538 +0,0 @@
|
|||||||
/*
|
|
||||||
* $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"));
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* $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;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,441 +0,0 @@
|
|||||||
/*
|
|
||||||
* $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 );
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* 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__
|
|
||||||
|
|
Binary file not shown.
@ -1,203 +0,0 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
@ -1,827 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,439 +0,0 @@
|
|||||||
#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 */
|
|
Loading…
Reference in New Issue
Block a user